Back to Blog
Guides

Are QR Codes Safe? How to Spot a Malicious One Before You Scan

Aug 25, 20268 min read
Are QR Codes Safe? How to Spot a Malicious One Before You Scan

A QR code cannot install anything, cannot run anything, and cannot touch your phone on its own. It is a picture of some text. Every bad outcome anyone has ever had with one happened after the text was handed to an app — which is oddly good news, because it means the entire defence fits in the few seconds between the camera reading the code and you tapping the banner.

What a QR code actually is

The pattern encodes a string of characters. That is the whole mechanism. There is no executable, no payload, no scripting layer — the black-and-white squares are a fault-tolerant way of writing text on a physical surface so a camera can read it back.

So a QR code is exactly as dangerous as the text inside it, and the text is almost always a URL. Which reframes the question. "Is this QR code safe?" is not really answerable. "Is this destination safe?" is, and it is the same question you have already been answering about links in emails for twenty years.

The one thing QR adds is that you cannot see the destination in advance. A link in an email shows you its text. A square of pixels on a lamppost shows you nothing at all. That gap is the entire attack surface, and closing it is mostly free.

The four ways a QR code goes bad

1. Somebody stuck a new one over the real one

This is the common one, and it is not a hacking story — it is a story about adhesive. A restaurant table, a parking meter, an EV charger, a rental scooter, a poster in a station. All of them are unattended surfaces displaying a code that people scan without thinking, and all of them can have a different sticker pressed on top in about two seconds.

The replacement code often points at a convincing copy of the payment page you expected. Nothing was compromised. The business's real code is still underneath, working perfectly.

2. The URL is a lookalike

The destination reads as the right brand at a glance and is not. This works because most people read a URL left to right and stop at the first familiar word, and that is the opposite of how a domain is actually resolved.

3. It is not a link at all

A QR payload does not have to be a web address. It can be a Wi-Fi join string, a contact card, a prefilled SMS or phone number, a calendar entry, a deep link into an installed app, or a payment string. Most of those are harmless and genuinely useful — a Wi-Fi code on a guest-room card saves everyone typing a 24-character password. But they behave differently from a link, and a couple are worth a second look:

  • Wi-Fi join — connects you to somebody's network. Fine at your hotel. Less fine on a sticker in a car park.
  • Prefilled SMS or call — your phone will show you the number and the message before sending. Read them; premium-rate numbers are the whole trick.
  • Payment strings — check the amount and the recipient on the confirmation screen every single time, because that screen is the last honest thing in the chain.

4. The code is genuine and the destination changed

A dynamic QR code points at a short redirect URL, and the owner can change where that redirect goes at any time — that is the entire point of it, and it is why the printed flyer that went out with the wrong link is fixable. The flip side is that the printed square you scanned last year and the printed square you are scanning today are identical, and may no longer lead to the same place. If the account behind it was taken over, or the domain lapsed and someone else registered it, the physical code is unchanged and blameless.

This is a reason to be slightly warier of an old printed code than a new one, and a reason for anyone printing them to care about who holds the account. We wrote up the trade-off in full in static vs dynamic QR codes — the lock-in section is the relevant half.

The ten-second check

On both iOS and Android, the built-in camera does not open anything when it sees a code. It shows you the destination as a notification or banner and waits for you to tap it. That pause is the product feature that matters most, and skipping it is the only way most of this goes wrong.

Read the domain right to left. Find the first single slash after the https://. Everything before it is the domain. Now read the last two labels before that slash — that is who you are actually talking to. Everything to the left of them is decoration that anybody can set to anything:

  • https://paypal.com.secure-billing.xyz/login → the domain is secure-billing.xyz. "paypal.com" is a subdomain the attacker named.
  • https://accounts.google.com/signin → the domain is google.com. Genuine.
  • https://menu.thelocalbistro.co.uk/table/12 → the domain is thelocalbistro.co.uk. Genuine, and the subdomain is doing an honest job.

Two more things worth a glance in that banner: a URL shortener hides the real destination behind another hop, which is not evidence of anything on its own but is a reason to be sure of the surface it was printed on; and a destination that immediately asks for a password, a card number or a one-time code when all you wanted was a menu deserves the whole ten seconds rather than two.

The check that beats reading the URL

Look at the code itself before you look at your screen. The physical attack is the common one, and it leaves physical evidence:

  • Is it a sticker on top of something? Run a fingernail along the edge. A raised corner, a bubble, or a second layer under a slightly-too-white square is the tell.
  • Does it match the thing it is on? A printed menu card with a code in the house typeface is a different proposition from a home-printed square taped to a laminate table.
  • Is it crooked? A code that is misaligned with the artwork around it was almost certainly not applied by whoever designed the artwork.
  • Is it the only one? Ten tables with the code printed into the menu and one table with a sticker is a question worth asking a member of staff.

If something is off, there is a free alternative that always works: type the business's address yourself, or ask. Nobody has ever regretted not scanning a sticker.

If you print QR codes, you are on the other side of this

The tampering happens to businesses, not just to the people scanning. Your customer's bad afternoon becomes your reputation. A few things genuinely help, and they are all cheap:

  • Print the destination in words next to the code. "Menu at thelocalbistro.co.uk" costs nothing, gives every customer something to compare the banner against, and gives them a way in when the code is covered.
  • Print it into the material, not onto a sticker. A code that is part of the menu card, the window vinyl or the moulded panel cannot be peeled off, and a sticker over it is obvious. Where a sticker is unavoidable, use a tamper-evident one.
  • Use a domain your customers recognise. A code that lands on your own name is one a customer can verify. A code that lands on a generator's shared domain is one they cannot.
  • Check the surface, on a schedule. Whoever wipes the tables can look at the codes. It takes a minute and it is the only control that catches the sticker.

A dynamic code helps with the aftermath rather than the attack: if a destination is ever compromised or simply wrong, you re-point it from the dashboard and every printed copy in the world follows, with no reprint. And because dynamic codes route through a redirect, the scan counts are visible — an unexpected pattern in the numbers is sometimes the first sign that something on a table is not yours. Neither of those inspects a destination for you. Nothing here does; be suspicious of any generator that says otherwise.

If you run a restaurant, the table-code question comes with a whole set of its own trade-offs — we covered those in the restaurant owner's guide to QR menus.

If you already scanned one

Scanning, by itself, does nothing. What matters is what happened next:

  • You looked at a page and left. Nothing to do.
  • You typed a password. Change it now, on the real site, reached by typing the address yourself. Change it anywhere else you reused it, and turn on two-factor authentication while you are in there.
  • You entered card details. Call your bank, freeze the card. They deal with this daily.
  • You approved a payment. Contact your bank or the payment app immediately — speed is the only thing that helps.
  • You installed something. Uninstall it, then check which apps hold accessibility and admin permissions.
  • It was a business's code. Tell them. They usually have no idea, and they are the only ones who can peel the sticker off.

The short version

QR codes are not dangerous; unverified destinations are, and they were dangerous before anybody printed one on a table. Look at the square before you scan it, read the domain right to left in the banner before you tap it, and never enter a credential on a page you arrived at from an unattended surface. That is the whole discipline, and it takes about ten seconds.

→ Make a QR code for your own domain

Ready to create beautiful QR codes?

Make your own in 30 seconds — no signup required to try.