Point a phone at a QR code and it offers to join a network, save a contact or open a page. It feels as if the code "knows" what it is. It does not. A QR code stores a string of characters and nothing else. The phone reads the string, looks at how it starts, and guesses what you want to do with it. This article walks through the text formats behind the common codes, shows what a scanner does with each one, and points out the mistakes that make a code scan but behave wrongly.
All the examples below were run through the parser in our QR code scanner, which reads codes from a photo, a screenshot or your camera and shows the decoded text before anything is opened.
The code is just text
The black and white modules encode bytes, plus error correction so the code survives a scratch or a logo in the middle. Once the scanner has fixed any damage, it hands over one plain string. Everything else, the "Join network" button, the contact card preview, the map pin, is the scanner's interpretation of that string.
That has two consequences. First, any text editor can show you exactly what a code contains, as long as you decode it without acting on it. Second, the type of a code is decided purely by a prefix such as WIFI:, BEGIN:VCARD or https://. Get the prefix or the punctuation slightly wrong and the phone treats your carefully prepared Wi-Fi code as a random sentence.
Wi-Fi codes: WIFI:
A Wi-Fi code is a short list of key:value pairs separated by semicolons, ending with two semicolons:
WIFI:T:WPA;S:Cafe Sen;P:12345678;;T is the security type (WPA, WEP or nopass for an open network), S is the network name (SSID), P the password and H:true marks a hidden network. The order of the pairs does not matter. Our scanner reads that line as SSID "Cafe Sen", security WPA, password "12345678".
The trap is punctuation inside the values. The semicolon ends a field, so a password that contains one has to escape it with a backslash, and the same goes for :, ,, " and the backslash itself. Here is the same café with the password hoa;sen:2024, written twice:
WIFI:T:WPA;S:Cafe Sen;P:hoa\;sen\:2024;;
WIFI:T:WPA;S:Cafe Sen;P:hoa;sen:2024;;The first line decodes to the password hoa;sen:2024. The second decodes to the password hoa, because the first semicolon ended the field and sen:2024 was read as an unknown key. The code scans perfectly, the phone tries to join, and the join fails with a "wrong password" message that sends everybody to the counter. A good generator escapes these characters for you; a hand-written payload often does not.
When there is no password and no type, as in WIFI:S:Guest;;, the network is treated as open. The scanner marks that with a warning, because anybody nearby can read traffic on an open network.
Contact cards: vCard and MECARD
A contact code usually holds a vCard, the same format address books export as a .vcf file:
BEGIN:VCARD
VERSION:3.0
N:Nguyen;An;;;
FN:Nguyen An
ORG:Sen Coffee
TEL;TYPE=CELL:+84 90 123 4567
EMAIL:[email protected]
END:VCARDN is the structured name (family; given; additional; prefix; suffix) and FN the display name. Our scanner shows this as the name "Nguyen An", the organisation, a mobile number tagged cell and the e-mail address, and offers it as a .vcf file you can save.
Some Android phones and older generators use the shorter MECARD format instead: MECARD:N:Nguyen,An;TEL:+84901234567;EMAIL:[email protected];;. Note that its N field puts the family name first, separated by a comma, so a scanner that reads it correctly shows "An Nguyen".
A vCard is the longest of the common payloads. Every extra line, a second phone, an address, a note, makes the code denser and harder to scan from a business card. Keep the card to what someone actually needs on the spot.
Links, and how a scanner judges them
A link is the simplest payload: the whole URL is the text. A scanner that is careful splits it up before you open it. For https://example.com/menu?table=12&lang=vi#drinks our scanner shows the scheme https, the host example.com, the path /menu, the parameters table = 12 and lang = vi, and the fragment drinks. Reading the host is what matters, because the host decides who receives your visit.
The scanner raises warnings on patterns that are legal but often abused:
| Payload | What the scanner flags |
|---|---|
http://xn--pple-43d.com/login | not encrypted (http), and a punycode host: xn-- names can look like a familiar brand once the browser displays them |
https://user:[email protected]/admin | credentials inside the link, and a bare IP address instead of a name |
javascript:alert(1) | an unsafe scheme; it is shown as text and never offered as a link |
A bare www.example.com is read as a web address and opened over https. Plain text that is not a known format, such as Table 12 - ask for the set menu, is simply shown as text.
E-mail, SMS, phone, location and 2FA
The rest of the common formats are URI schemes:
mailto:[email protected]?subject=Order%2012&body=Hiprepares an e-mail with the subject "Order 12". Spaces must be percent-encoded as%20.SMSTO:+84901234567:STOPprepares a text message with the body "STOP". It never sends by itself, but a code like this on a poster can make you subscribe to something if you press send without reading.tel:+84901234567offers to call a number.geo:21.0285,105.8542?q=Hoan%20Kiemis a latitude and longitude with a label; our scanner offers it as a map link rather than opening an app.otpauth://totp/Example:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Exampleis the code an authenticator app scans when you set up two-factor login. Thesecretis the key that generates every future code, so the scanner hides it by default and warns you. Treat a screenshot of this code like a password. The TOTP code generator explains what that secret does.
Common mistakes
- Unescaped `;` or `:` in a Wi-Fi password. The code scans and the password is silently cut short.
- A long payload on a small print. Larger content means more modules; a dense code printed at 2 cm often fails on older cameras. Shorten the text or print bigger.
- Trusting the poster, not the host. Stickers are pasted over real codes. Read the host before opening a link, especially if it asks you to log in or pay.
- Sharing a setup code. An
otpauth://QR code is a secret, not a convenience. - Light code on a dark background. Some scanners only look for dark modules on light; ours also tries the inverted image, but not every phone does.
If you need to make a code rather than read one, the QR code generator builds Wi-Fi, contact and link payloads with the escaping done for you. For why a static code like these never expires, see static vs dynamic QR codes.