QR Code Reader

Read QR codes from an image, pasted screenshot or camera. Finds several codes per image, shows the real host of a link, and keeps Shift_JIS/GBK text readable.

  • Images and camera frames stay in your browser; URL mode downloads the image from the address you enter
  • Free · No Sign-Up
Enter an http:// or https:// image address and choose Decode or press Enter. The image server must allow CORS. The request sends no cookies or referrer; when it fails, save the image and drop it here.

URL mode contacts the image host, which can see your IP address.

Scan with camera asks for permission and prefers the rear camera. Frames stay in this browser. Scanning stops on the first frame with a code; Stop camera, Clear or Ctrl/⌘+L also stops it. A browser with camera support and a secure page is required.
Image Choose one image, drop it here, or paste a screenshot with Ctrl+V / ⌘V. The browser must support its format; take a screenshot of PDFs. zxing-wasm 3.1.4 (ZXing C++ in WebAssembly) loads from this site on first use (about 420 KB). It reads QR, Micro QR and rMQR, up to 16 codes per image, and scales images above 16,777,216 pixels.

Drop an image, click to choose one, or paste a screenshot (Ctrl+V / ⌘V)

Choose, drop or paste another image

PNG · JPG · GIF · WebP · BMP · AVIF — one image can hold several codes

Examples, details and FAQ Worked examples, how it compares with other tools, and answers to common questions.

What the Reader Shows

Text in the code starts withBadgeShown as
http:// or https://URLLink (opens only when you click it), the real host, warnings
WIFI:Wi-FiSSID, password, encryption, hidden flag; backslash escapes removed (ZXing: Barcode Contents)
BEGIN:VCARD or MECARD:ContactName, organization, phone, email, address, URL, note
mailto: or MATMSG:EmailTo, Cc, subject, body (RFC 6068)
tel:PhoneNumber (RFC 3966)
sms: or SMSTO:SMSNumber and message (RFC 5724)
geo:LocationLatitude, longitude, altitude and an OpenStreetMap link (RFC 5870)
any other scheme:App linkText only, with a note that only an app opens it
anything elseTextText as stored

Structured cards keep the raw text one click away, and every card has a Bytes section with the stored bytes in hex.

These are the results the tool gave for codes generated with the page’s own QR library:

  • A business card code (BEGIN:VCARD … FN:Ana Rivera … TEL;TYPE=CELL:+1-415-555-0134) shows Contact with Name Ana Rivera, Organization Example Labs, Phone +1-415-555-0134 and Email ana@example.com.
  • A screenshot with three codes side by side gives three numbered cards in reading order: Wi-Fi (CafeGuest / latte2026 / WPA), URL (https://example.com/menu), Phone (+81312345678). The preview numbers the codes on the image.
  • geo:37.5665,126.9780 shows Location with a link to that point on OpenStreetMap.

The FTC warns that scammers paste their own QR codes over the ones on parking meters and send codes by email and text, and advises you to inspect the URL before you open it. Two tricks are hard to see on a phone screen, and the reader flags both:

  • https://citypark.example.gov@pay-meter.example.net/zone/4471 looks like a city domain. The host line says pay-meter.example.net, and a warning explains that everything before @ is a user name.
  • https://exаmple.com/login uses a Cyrillic а. The host line shows the punycode form xn—exmple-4nf.com with a look-alike warning.

Only http and https text becomes a link. javascript:alert(document.domain) is shown as an App link with the warning that it is not opened, and so are data:, vbscript: and file: addresses. To take a long address apart (query parameters, fragments, encoded characters), paste it into the URL Parser.

Photos, Screenshots and Hard Images

  • Several codes in one image are all decoded, up to 16, and numbered from the top left.
  • Light-on-dark codes, rotated codes and codes without a white margin are read as well.
  • Large photos are decoded at full resolution up to 16,777,216 pixels (the canvas limit of iOS Safari); bigger images are scaled down first, and the status line says so. A 4000×3000 phone-style photo with a small code took about 1.2 s in desktop Chromium on the test machine.
  • Tiny codes need roughly 1.5 image pixels per module: a 33-module code at 45×45 pixels failed, at 60×60 it read.

Text Encoding: UTF-8, Shift_JIS, GBK and ECI

A QR code stores bytes. It can declare their character set with an ECI header (ISO/IEC 18004), but most generators just write UTF-8. With an ECI, the card says so (for example UTF-8 (ECI 26)). Without one, the reader follows ZXing’s guessing rule: valid UTF-8 is UTF-8, then Shift_JIS or ISO-8859-1. The card labels the result (guessed), and the Text encoding menu re-decodes the same bytes as UTF-8, Shift_JIS, GB18030/GBK, Big5, EUC-KR, ISO-8859-1 or UTF-16.

In tests, a code holding the Shift_JIS bytes of 東京都千代田区丸の内 カフェ decoded correctly on this page. GBK bytes for 你好,世界。二维码测试 were guessed as ISO-8859-1 on the English page, as ZXing does, and read correctly after choosing GB18030 in the menu. Bytes that are not text in any encoding get the Binary badge and open in hex.

How It Compares

Tested on 2026-09-30 with the same seven images in desktop Chromium:

ImageZeroToolScanQRDNS Checker
Three codes in one image3 cards3 foundStill “Scanning…” after 10 s
Shift_JIS text, no ECICorrect text”QR code detected!”, empty text”Empty QR Code”
GBK text, no ECICorrect after picking GB18030Empty textStill “Scanning…” after 11 s
Light-on-dark codeReadReadRead
Gray on gray (110/170)ReadRead with its fallback engineRead
javascript: payloadText with warningPlain textPlain text
4000×3000 photo, small codeRead (about 1.2 s)“No QR code found”Read

Given https://paypal.com@evil.example/login, ScanQR shows the address as an Open Link button with no warning; ZeroTool shows the host evil.example and the @ warning.

Limits

  • One image at a time. PDFs need a screenshot first; HEIC works only where the browser displays it (Safari).
  • The first decode waits for the 420 KB decoder; after that, decoding is local and works offline until you reload.
  • Only the QR family is read. For EAN, UPC or Code 128 barcodes this page shows nothing; the Barcode Generator makes them but does not read them.
  • Chrome’s built-in BarcodeDetector is not used: MDN’s compatibility data lists it only on macOS, ChromeOS and Android, not in Firefox, and behind a flag in Safari.
  • URL mode works only when the image’s server allows cross-origin requests (CORS). Otherwise save the image and drop it in.
  • Wi-Fi cards show SSID, password, encryption and the hidden flag; WPA2-Enterprise fields such as E: and I: stay in the raw text.

To make a code rather than read one, use the QR Code Generator or, for network logins, the Wi-Fi QR Code Generator.

FAQ

Is my image uploaded to a server?

No. Files, pasted screenshots and camera frames are decoded in your browser by zxing-wasm, which this site serves from its own /vendor folder. The only request that leaves the page is the one you ask for in URL mode: the browser downloads the image from the address you type, without cookies or a referrer.

Can it read a QR code from a screenshot?

Yes. Take the screenshot, click the page and press Ctrl+V (⌘V on a Mac). If the screenshot shows several codes, each one gets its own numbered result card.

Why does the result say the link goes to a different site?

Everything between https:// and an @ sign is a user name, not the site. https://citypark.example.gov@pay-meter.example.net/ opens pay-meter.example.net. The reader shows the host the browser would really open and warns when an @ or a punycode (xn--) host is in the address.

Why is my decoded text garbled?

The code probably stores Shift_JIS, GBK or EUC-KR bytes without saying so. Open the Text encoding menu under the result and pick the right one; the Bytes section shows the raw bytes in hex.

What does the camera scanner need?

A browser with the standard camera API (getUserMedia), an HTTPS page and your permission. The page asks for the camera only when you press Scan with camera, prefers the rear camera, and decodes the frames on the device. If you deny access, upload a photo instead.