Explainer
Are QR codes safe to scan?
The pattern itself carries no executable code and cannot infect a phone. The risk is entirely about where it sends you, and about the fact that a human cannot read a destination before committing to it.
Updated
The honest answer has two halves. The format is harmless: a QR code is a way of writing text as squares, and text does not execute. The delivery is not: a code hides its destination behind a pattern nobody can read, which removes the single habit most people rely on to spot a bad link. Almost every genuine risk lives in that second half.
What the format can and cannot do
A code stores characters. A decoder reads the characters and hands them to the operating system, which decides what kind of thing they are — a web address, a phone number, a network credential, a block of plain text. Nothing in that chain runs code from the pattern.
This rules out an entire category of worry. There is no such thing as a QR code that infects a phone on sight, and claims to the contrary are describing a different attack with a code attached to the front of it. Historic decoder vulnerabilities have existed, as they do in any image parser, but they are rare, patched quickly, and not what any real-world campaign relies on.
What the format genuinely enables is misdirection. The characters can say anything, and a person cannot inspect them before the scan.
Quishing, and why it works so well
Phishing by QR code took off for reasons that have little to do with the technology. Email security gateways spent years scanning text for suspicious links and treating embedded images as decoration, which made a code an easy way past them. At the same time the pandemic normalised scanning codes in public places for menus, payments and check-ins, so nobody found the request odd.
The physical version is more effective still, and requires no technical ability: print a sticker and put it over an existing code. Parking meters, EV chargers, restaurant tables and delivery lockers have all been hit this way. The legitimate context does the persuading. Someone standing at a parking meter expects to scan and pay, so a page asking for card details fits the situation perfectly.
Notice that neither variant involves anything clever about QR codes. They exploit the gap between “I scanned something” and “I can see where it goes”.
What actually helps
Read the preview banner. Both iOS and Android show the destination and wait for you to confirm. That banner is the check that replaces reading a link, and it only helps if you actually read it rather than tapping through by reflex.
Look at the registered domain, not the whole string. The part that matters
is immediately before the first single slash. Everything else is attacker-
controlled padding, and a subdomain reading secure.yourbank.com.verify-id.example
belongs to example, not to a bank.
Check whether the code is a sticker. For anything in a public place, this is the highest-value five-second check available. Peeling edges, a colour mismatch with surrounding print, or a label covering other text are all reasons to type the address instead.
Never enter credentials on a page you arrived at by scanning. Not because the scan is dangerous, but because there is no way to establish that the page is genuine from that starting point. Open the app or type the address you already know.
Treat downloads as a separate decision. A code that leads to a file is asking for a second action with different consequences. Judge the file on its own merits, not on the fact that a code introduced it.
The privacy question people miss
Security gets the attention, but tracking is the more routine exposure. A dynamic code routes every scan through a redirect service before forwarding you, and that service records the request — timestamp, approximate location, device and referrer — before you have loaded anything. The person who printed the code sees an analytics dashboard. You saw a menu.
That is not an attack, and it is often disclosed somewhere. It is worth knowing because it is invisible at scan time and because it is a real difference between the two kinds of code, covered in full in the static and dynamic comparison.
There is a matching consideration when you are the one generating codes. Any generator that builds the pattern on a server has, by definition, received whatever you typed — including Wi-Fi passwords, contact details and payment identifiers. That is why every generator on this site encodes in the browser and sends nothing, and why the network-tab check described above is worth running on any tool that asks for a credential.
A proportionate summary
Scanning a code from a printed menu, a product box or a business card is ordinary and fine. Scanning one from an unsolicited email, a letter claiming an unpaid fee, or a sticker applied over a payment terminal deserves the same scepticism the equivalent link would get.
The format is not the risk. The missing preview is, and the platform now gives you one. Use it.