QR code decoder

Read a QR code from an image, and see where it leads before opening anything. Nothing is ever opened or run automatically.

Need to make one? Create a QR code

Transparency

The image is read in your browser, by the scripts listed below. Neither the image nor its content leaves this page.

Enforced by your browser
This page's Content Security Policy allows a single destination, the site's audience measurement (connect-src https://stats.r-no.fr, see below), and forbids any form submission (form-action 'none'), so even a bug could not send your image or its content anywhere. The image is displayed through a blob: address, which is local to your browser. You can read the policy at the top of the page source.
Audience measurement
Like every page of the site, this one counts its visit with Umami, installed on R-no’s own server (stats.r-no.fr). It receives the address of the page, without parameters or anchor, the site you came from (its domain only), your browser, system, language and screen size, and the country, region and city deduced from your IP address, which is not kept. It never receives what you type, nor the result of the tool. No cookie, nothing stored in your browser; if your browser asks not to be tracked (Do Not Track), nothing is measured. The data is erased after 25 months.
  • /commun/mesure.js: the filter applied before each sending, written for R-no Toolbox. 1.4 kB
    SHA-256 225eec74fd12623d82fc05ee7d222be629ce454d081c129e8d1e249ed37ee716
  • https://stats.r-no.fr/m.js: Umami’s tracker, open source (MIT), served by the measurement server. Its fingerprint is not shown here: it changes with each version of Umami, and you cannot check from your browser that it is the published code. For that part, you have to trust R-no.
Nothing runs by itself
The content is shown as plain text. A web link (http or https) is offered only after it has been analysed, and opens only if you click it, in a new tab that does not learn where you came from. Other kinds of links (javascript:, data:, app links…) are never made clickable. Wi-Fi networks and contacts are displayed, never added to your device. There is no camera access: only a file you choose.
What is stored
No cookie, and nothing in the address. The image and its content are never stored, and they are cleared when you leave the page. Your language is given by the address itself (/en/ or /fr/): nothing is stored to remember it. Like any website, the server records the download of the page and its files in its access logs (IP address, date and time, address requested, browser name). It never receives your image. The “Check for lookalike characters” button hands the link to domains/lookalike after a #, which browsers never send to the server.
Code that runs here
  • app.js: the tool itself, written for R-no Toolbox: it reads the image, analyses the content and displays it. Not minified. 24.1 kB
    SHA-256 5b8bbfd449c2a46b0874aa2720ac3854ff0cb36cf4001cfb43c90e84ba53fc44
  • jsQR.js: the jsQR decoder, version 1.4.0, which finds and reads the QR code in the image. Apache License 2.0. Not minified. 256.9 kB
    SHA-256 bc40c8a15196236b2314db0856f72ca0b49980cd5413b8c852a7349f5fee0859
  • textes.js: the French messages of the tool, shown by its script (the rest of the French page is written into its HTML when the site is built). It only defines texts, with no logic. 8.5 kB
    SHA-256 e43501ee155c3190ff60bcd300b49983eef75f128843d03cf32d8f4a16c1ab03
  • /commun/langue.js: the language helper, the same on every page of the site. It reads the language of the page and gives the tool its messages in that language. It stores nothing. 1.6 kB
    SHA-256 80f76f69773ef628d36d09bf8387cfedebda4529210d7120649b6f5603310631
  • jsQR.LICENSE.txt: the full text of jsQR's license.
Where jsQR.js comes from
It is the file published on npm by its authors (jsqr 1.4.0, dist/jsQR.js), unchanged down to the last byte, so its fingerprint can be compared with the published package. npm checks the package's integrity against the lockfile; on every deployment the file is fetched again and compared byte for byte with the one served here, and the deployment stops if they differ. jsQR has not been updated since 2021; the QR code standard has not changed either.
Check it yourself
Download a file and compare its fingerprint with the one above:
curl -s https://r-no.fr/qr-code/decoder/jsQR.js | shasum -a 256
Limits
Only one QR code is read per image; if there are several, crop the image. Very blurry, distorted or badly lit pictures may not be read, nor Micro QR codes or other kinds of barcodes. The link analysis looks for common tricks (hidden destination, look-alike characters, unencrypted link, misleading @…); it cannot tell a safe site from a dangerous one, and it marks the site name approximately for some country domains. Some formats are recognised and laid out (Wi-Fi, contact, e-mail, SMS, phone, location, event); anything else is shown as text.