To decode a QR code from a local PNG in JavaScript, let the user choose the file, load it into an HTMLImageElement, and pass that image to a QR decoder. With ZXing’s browser library, the central call is BrowserQRCodeReader.decodeFromImage(img). The returned result exposes the decoded string as result.text. A canvas-based approach is also possible when your decoder expects raw RGBA pixels rather than an image element.
This workflow reads an existing file; it does not require camera permission or a live video stream. The examples below report “not found” and validation failures as normal input errors instead of leaving an uncaught promise.
What you need
- A browser page served from a local development server or your normal web host. Opening an HTML file directly may work in some browsers, but a server avoids module and security-policy surprises.
- A PNG selected with an
<input type="file" accept="image/png">control. - A decoder library. ZXing’s TypeScript project documents decoding from an image element and from an image URL in its QR image example and project documentation.
No success-rate, image-size threshold, or cross-browser guarantee is established by those examples. A badly cropped, blurry, tiny, rotated, or partially obscured QR image can legitimately fail.
Browser solution with ZXing
1. Add a file picker and result area
Create a page with a file input and an element for status. The accept attribute guides the chooser but is not a security boundary, so still validate the selected file in JavaScript.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
- Continuous Usage All Day: The EY-H2 USB barcode scanner is designed to always be ready for the next scan, which significantly reduces downtime and repair costs; it shortens checkout lines, improves customer service, and boosts business productivity
- Plug and Play: Eyoyo wired barcode scanner is connected via a USB cable, with no need to install any driver or software; It offers effortless connection and is compatible with Windows, Mac, Android, and Linux; Seamlessly works with Quickbook, Word, Excel, Novell, and all common software
- Supports Multiple 1D/2D Barcodes: Eyoyo QR code scanner scan with most 1D 2D barcodes with ease; 1D Barcodes: EAN, UPC, Code 39, Code 93, Code 128, UCC/EAN 128, Codabar, Interleaved 2 of 5, ITF-6, ITF-14, ISBN, ISSN, MSI-Plessey, GS1 Databar, Code 11, Industrial 25, Matrix 2 of 5, etc. 2D Barcodes: QR, DataMatrix, PDF417, and so on
- Supports Screen Scanning: The Eyoyo 2D scanner is capable of reading barcodes from smartphone screens, such as mobile coupons, digital wallets, and digital loyalty cards; Before scanning, simply turn your screen brightness to the maximum
- Sturdy Anti-Shock and Durable Design: The Eyoyo 2D barcode scanner features an ergonomic design made of high-quality ABS, enabling it to withstand repeated drops from 5 ft/1.5 m high onto the concrete ground; The durable plastic material ensures a long service life
<label>
PNG file
<input id="pngFile" type="file" accept="image/png">
</label>
<p id="status" role="status">Choose a PNG image.</p>
<pre id="decoded" hidden></pre>
<script type="module" src="./decode-qr.js"></script>
2. Install and import the browser reader
Install the browser package in your project, then verify the API against the version you install. The package name and exports can change over time.
npm install @zxing/browser
In decode-qr.js:
import { BrowserQRCodeReader } from "@zxing/browser";
const input = document.querySelector("#pngFile");
const status = document.querySelector("#status");
const decoded = document.querySelector("#decoded");
input.addEventListener("change", async () => {
const file = input.files?.[0];
decoded.hidden = true;
decoded.textContent = "";
if (!file) {
status.textContent = "Choose a PNG image.";
return;
}
if (file.type !== "image/png") {
status.textContent = "Please choose a PNG file.";
input.value = "";
return;
}
const objectUrl = URL.createObjectURL(file);
const image = new Image();
image.decoding = "async";
status.textContent = "Loading image…";
try {
await new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = () => reject(new Error("The PNG could not be decoded by the browser."));
image.src = objectUrl;
});
status.textContent = "Decoding…";
const reader = new BrowserQRCodeReader();
const result = await reader.decodeFromImage(image);
decoded.textContent = result.text;
decoded.hidden = false;
status.textContent = "QR code decoded.";
} catch (error) {
const name = error?.name || "";
if (name === "NotFoundException") {
status.textContent = "No QR code was found in this image. Choose a clearer or correctly cropped PNG.";
} else if (name === "ChecksumException" || name === "FormatException") {
status.textContent = "A QR-like pattern was found, but its data failed validation. Try the original PNG.";
} else {
console.error(error);
status.textContent = "The image could not be decoded. Check that it is a valid PNG and try again.";
}
} finally {
URL.revokeObjectURL(objectUrl);
}
});
The important ordering is deliberate: create the object URL, wait for image.onload, then decode. Revoking the URL in finally releases the browser resource even when loading or decoding fails. ZXing’s reader reference names NotFoundException, ChecksumException, and FormatException as distinct failure cases; your installed JavaScript wrapper may expose them differently, so keep a generic fallback.
Decode by URL instead of constructing an image element
ZXing also documents an image-URL path. That is useful when the image is already hosted and same-origin or otherwise permitted by the browser:
const reader = new BrowserQRCodeReader();
const result = await reader.decodeFromImageUrl("/images/code.png");
console.log(result.text);
For a user-selected local file, an object URL is the safer direct equivalent because the file never needs to be uploaded to your server.
Rank #2
- 【Battery Level Indicator and 2200mAh Capacity】Larger battery enables longer continuous usage and twice the stand-by time of others. With the unique battery indicator light showing the remaining battery level, no more Low Battery Anxiety.
- 【Ergonomic Design】 The curved handle is extended and thickened, tailor-made for North America customers. Specially designed smooth and flat trigger for better grip. 【Package Includes】Barcode Scanner x1, USB Cable x1, Dongle x1, User Manual x1.
- 【Anti-Shock Silicone】 The orange anti-shock silicone protective cover can avoid scratches and friction while falling from the height of 6.56 feet. IP54 technology protects the wireless barcode scanner from dust.
- 【2.4 GHz Wireless plus USB 2.0 Wired Connection】 Plug and play with the USB receiver or the USB cable, no driver installation needed. Easy and quick to set up. Wireless transmission distance reaches up to 328 ft. in barrier free environment.
- 【Digital and Printed 1D 2D QR Bar Code Symbologies】1D: Codabar, Code 11, Code93, MSI, Code 128, UCC/EAN-128, Code 39, EAN-8, EAN-13, UPC-A, ISBN, Industrial 25, Interleaved 25, Standard25, Matrix 2D: QR, DataMatrix, Aztec, Hanxin, Micro PDF417. (Note: Not compatible with Square.)
Canvas and RGBA pixels: an alternative route
Some decoders do not accept an HTMLImageElement. They expect an object shaped like canvas ImageData: { width, height, data }, where data is RGBA pixel data. The qr npm package listing describes a decodeQR API with that input shape and an image-file example.
import { decodeQR } from "qr";
async function decodePngWithCanvas(file) {
const url = URL.createObjectURL(file);
const image = new Image();
try {
await new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = reject;
image.src = url;
});
const canvas = document.createElement("canvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
const context = canvas.getContext("2d", { willReadFrequently: true });
if (!context) throw new Error("Canvas 2D is unavailable.");
context.drawImage(image, 0, 0);
const pixels = context.getImageData(0, 0, canvas.width, canvas.height);
return decodeQR({
width: pixels.width,
height: pixels.height,
data: pixels.data
});
} finally {
URL.revokeObjectURL(url);
}
}
// Example use:
try {
const text = await decodePngWithCanvas(file);
console.log(text);
} catch (error) {
console.error("QR decode failed", error);
}
Check the installed package’s current export names and return type before shipping. The documented pixel contract is the useful part: wait for the image, draw it at its natural dimensions, read ImageData, and pass width, height, and RGBA bytes. This route gives you a place to preprocess pixels, but it adds a full-size canvas allocation.
Which route should you choose?
| Concern | ZXing browser reader | Canvas plus pixel decoder |
|---|---|---|
| Input | Image element or documented image URL | Width, height, and RGBA data matching ImageData |
| Integration | Short path for a browser file picker | More control, but you manage canvas drawing and memory |
| Format scope | Use the QR reader/API documented by your installed version | Depends entirely on the selected package and version |
| Failure handling | Reader exceptions can distinguish not-found and validation failures | Use the package’s documented errors or normalize them yourself |
| Runtime | Designed for browser APIs | Browser canvas is straightforward; a Node.js image pipeline needs separate, version-checked setup |
No cited material establishes a benchmark proving one route is faster or more accurate. Choose based on your runtime, the decoder’s supported formats, and how much pixel preprocessing you need.
Improving difficult decodes
- Use the original PNG. Avoid screenshots of a QR code that has already been resized or compressed.
- Keep the quiet zone. A QR code generally needs the blank margin around its modules; aggressive cropping can remove useful context.
- Preserve resolution. Do not draw a large image into a tiny canvas before decoding.
- Try a clean crop. If the PNG contains a busy page, crop to the QR code while retaining a small white border.
- Handle orientation. Rotate a sideways image before decoding if the library does not try orientations itself.
- Do not block the interface. Very large files create large decoded pixel buffers. For repeated or expensive work, move preprocessing and decoding to a Web Worker if your chosen library supports worker use.
These are engineering tactics, not guaranteed thresholds. Test with the image types your application actually receives.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
- 【Battery Level Indicator and 2200mAh Capacity】Larger battery enables longer continuous usage and twice the stand-by time of others. With the unique battery indicator light showing the remaining battery level, no more Low Battery Anxiety.
- 【Ergonomic Design】 The curved handle is extended and thickened, tailor-made for North America customers. Specially designed smooth and flat trigger for better grip. 【Package Includes】Barcode Scanner x1, USB Cable x1, Dongle x1, User Manual x1
- 【Anti-Shock Silicone】 The orange anti-shock silicone protective cover can avoid scratches and friction while falling from the height of 6.56 feet. IP54 technology protects the wireless barcode scanner from dust.
- 【2.4 GHz Wireless + USB 2.0 Wired Connection】 Plug and play with the USB receiver or the USB cable, no driver installation needed. Easy and quick to set up. Wireless transmission distance reaches up to 328 ft. in barrier free environment.
- 【Digital and Printed 1D 2D QR Bar Code Symbologies】1D: Codabar, Code 11, Code93, MSI, Code 128, UCC/EAN-128, Code 39, EAN-8, EAN-13, UPC-A, ISBN, Industrial 25, Interleaved 25, Standard25, Matrix 2D: QR, DataMatrix, PDF417, Aztec, Hanxin, Micro PDF417. (Note: Not compatible with Square.)
Security and privacy considerations
Object URLs keep a selected file in the browser; the examples do not upload it. Treat decoded text as untrusted input. If you display it as HTML, escape it or assign it with textContent, as the examples do. If you turn a decoded URL into a link, consider warning users before navigation and applying your normal URL allowlist or scheme checks. Do not execute decoded content as JavaScript.
For untrusted files, enforce practical limits before creating a canvas (for example, reject unexpectedly large dimensions) and avoid retaining object URLs after use. A PNG’s MIME type can be missing or misleading, so applications with stronger security requirements should inspect the file signature and rely on a server-side validation policy as well.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting
“No QR code found”
The file loaded, but the decoder found no valid QR candidate. Try the original, higher-resolution PNG; include the white border; remove surrounding graphics; and verify that the image is not a different barcode format.
Checksum or format validation failure
A QR-like pattern was detected, but the payload did not pass validation. This commonly points to blur, scaling artifacts, occlusion, or an incomplete crop. Select a clean source rather than repeatedly retrying the same pixels.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
- 【Unique Designed Screen Setting】It allows you to customize the screen display according to your preferences. With this innovative feature, you can easily set the language, adjust volume settings, select connection options, and view stored and total barcodes. Experience unparalleled convenience and flexibility as you personalize the settings of your Tera HW0009 to suit your specific needs. 【Package Includes: Barcode Scanner x1, Charging Cradle x1, Charging Cable x1, User Manual x1】
- 【Superior Global CMOS Imaging Scanning】This advanced scanner excels in fast and accurate reading of both ordinary and high-density barcodes, including challenging formats like PDF417 found on driver's licenses. Its exceptional performance effortlessly handles various scanning scenarios, including underwater scanning, reading barcodes on silver paper, reflective materials, and more.
- 【Charging Cradle & 2500mAh Large Battery】Designed with a convenient charging cradle, the HW0009 barcode scanner allows you to easily charge it whenever it's not in use. In addition, the scanner itself is equipped with a powerful 2500mAh battery, ensuring seamless all-day operation without the need for frequent charging.
- 【3-in-1 Connections & Widely Compatible】 Tera HW0009 wireless barcode scanner can work with bluetooth & 2.4G wireless & usb wired. The transmission distance can be 328ft in barrier free environment and 114ft in obstacles environment using 2.4G USB dongle. It can be connected with a variety of devices, such as smartphones, computers, POS, tablets. In addition, it is also compatible with various operating systems, such as windows 11/10/8/7/xp, Mac OS, iOS, android, linux.
- 【1D 2D QR code Programmable】2D: QR code, Data Matrix, PDF417(including PDF417 on driver’s license), Aztec, Maxicode, Micro QR, Micro PDF417; 1D: UPC/EAN, Code 128/EAN128, GS1-128, ISBT-128, Standard 2 of 5, Matrix 2 of 5, Code 39, Code 32, Code 93, Code 11, Codabar, PLESSEY, MSI, GSI Databar, ITF-14, GS1.
The image never loads
Confirm that a file was selected, that the object URL is assigned before waiting, and that URL.revokeObjectURL is called only after loading and decoding finish. A rejected image.onerror usually means the browser could not parse the file as an image.
“BrowserQRCodeReader is not defined” or an import error
Make the script a module, install the package in the same project that serves the page, and check the installed package’s current export syntax. Do not mix a CDN build and a bundler import without following that build’s instructions.
Canvas security or blank pixels
A cross-origin hosted image can taint a canvas unless the server supplies appropriate CORS headers and the image is loaded with the matching crossOrigin setting. A local object URL selected by the user normally avoids that remote-origin problem.
Node.js requirement
This article’s complete implementation uses browser file and canvas APIs. Node.js needs an image decoder or canvas-compatible package plus a QR reader, and the exact recipe depends on current package versions. Select a library whose documentation explicitly supports your Node version; do not assume the browser API can be copied unchanged.
Best Value
- 【IP66 Waterproof Dustproof Mini Pocket 2D Scanner】Just bring this scanner with you. Anytime you want to collect data, just connect it with your device via Bluetooth or use the storage mode. 【Package Includes】Barcode Scanner x1, USB Cable x1, Dongle x1, User Manual x1.
- 【Waterproof Dustproof Silicone Port Plug】Newly designed waterproof and dustproof silicone port plug on marketplace, it enables better performance of the scanner in every working conditions. The silicone button on the scanner body enables every soft and smooth scanning experience.
- 【3-in-1 Connection Ways】This scanner works with Bluetooth, 2.4GHz wireless and USB 2.0 wired mode. The transmission distance can be 656ft in barrier free environment and 98 ft in an environment with obstacles using a 2.4G USB dongle. In addition, it is also compatible with various operating systems, such as windows 11/10/8/7/xp, Mac OS, iOS, android, linux.(Note: Not Compatible with Square)
- 【Vibration Alert】: When you need a quiet working environment, just turn the volume off and the vibration function will let you know if a barcode is detected.
- 【1D 2D QR Scanner】:Supports Both Digital and Printed 1D 2D QR Bar Code Symbologies: 1D Decode Capability: Codabar, Code 11, Code93, MSI, Code 128, UCC/EAN-128, Code 39, EAN-8, EAN-13, UPC-A, ISBN, Industrial 25, Interleaved 25, Standard 25, 2/5 Matrix 2D Decode Capability: QR, PDF417, Data Matrix, Aztec code, Maxi Code.
Or skip the browser setup
ScreenshotNeo is not a QR decoder for a local PNG. It is useful when the image you need is a webpage capture rather than an existing file: one request returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
For a webpage screenshot, call the API as documented at ScreenshotNeo’s documentation:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
There is a free allowance of 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account if your workflow starts with web pages and you want the capture step handled by an API.
FAQ
Do I need camera permission?
No. A static PNG can be decoded from a file input without camera access.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchCan I decode several PNG files?
Yes. Use multiple on the file input, then run the same load-and-decode function for each file and report each result independently.
Does decoding reveal the QR code’s destination is safe?
No. Decoding returns data; it does not validate or endorse a URL, payment request, or other payload.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

