Privacy Tools Guide

QR codes are not inherently dangerous — they are just URLs encoded as images. The danger lies in what happens when you scan them: you make an HTTP request that reveals your IP address, device fingerprint, and precise scan time to whoever controls the URL. QR codes in the physical world have made targeted tracking trivial in ways that were previously impossible.

What a QR Code Actually Contains

A QR code encodes a string of text, most commonly a URL. When you scan one:

  1. Your device decodes the URL
  2. Your camera app or OS opens a browser/app with that URL
  3. An HTTP request is made to that URL’s server
  4. The server receives: your IP address, user agent, Accept-Language header, referrer (if any), and an exact timestamp

A URL like https://tracker.example.com/qr/campaign_id_12345 can identify exactly which QR code you scanned, where it was physically placed, and correlate your scan with your identity if you are logged into a linked account.

Tracking Use Cases in the Wild

Restaurant Menus

Digital menus accessed via QR code often use URL shorteners or tracking links. The restaurant owner (or the digital menu service) can see:

Some services aggregate this data across hundreds of restaurants and build behavioral profiles.

Advertising QR Codes

A QR code on a bus shelter, magazine, or product packaging is typically a unique tracking URL. The advertiser knows:

Loyalty Program QR Codes

Your personal QR code at a coffee shop or pharmacy is an identifier that links every purchase to your identity, including non-loyalty purchases in the same transaction.

COVID Check-In QR Codes (Historical Example)

During 2020-2022, mandatory QR code check-ins at venues created location databases of millions of people. Several countries subsequently used this data for purposes other than contact tracing.

Technical Tracking Methods

Your device scans QR code
    └─ Makes request to: https://url.example.com/r/abc123?ts=1711100400
            └─ Server logs:
                ├─ IP address (geolocation to ~city)
                ├─ Timestamp (precise to millisecond)
                ├─ User-Agent (OS, browser, device model)
                ├─ Accept-Language (infers native language)
                └─ Cookies (if you've visited the domain before)

Advanced trackers also use:

Decode Before You Scan

Before pointing your camera at an unknown QR code, decode it with an offline tool or inspect the URL:

# On Linux: decode from an image without making any network request
sudo apt install zbar-tools
zbarimg qrcode.png
# URL=https://suspicious-tracker.com/r/campaign_id_123?src=poster_loc_5

# Python offline decode
pip3 install pyzbar Pillow
python3 -c "
from pyzbar.pyzbar import decode
from PIL import Image
result = decode(Image.open('qrcode.png'))
print(result[0].data.decode())
"

On mobile, use an app that shows you the decoded URL before opening it:

Scan Safely with a Privacy Layer

# On desktop: decode the URL, then open in a privacy browser
zbarimg qrcode.png | cut -d= -f2 | xargs -I{} firefox --new-tab {}

# Or pipe to Tor Browser
zbarimg qrcode.png | cut -d= -f2 | xargs torsocks curl -s -o /dev/null -w "%{http_code}"

For mobile scanning:

  1. Use a scanner app that shows the URL first
  2. Copy the URL instead of tapping it
  3. Expand URL shorteners before visiting: curl -sI https://bit.ly/abc | grep Location
  4. Open in Firefox Focus (auto-deletes cookies after each session) or a private tab
# Expand URL shorteners from the command line
expand_url() {
    curl -sIL "$1" | grep -i "^location:" | tail -1 | awk '{print $2}'
}
expand_url https://bit.ly/abc123

QR Code Phishing (Quishing)

A physical QR code is easy to replace — attackers place stickers over legitimate QR codes in parking lots, public transport, and EV charging stations. The replacement code leads to a phishing page that mimics the real service.

Signs of a tampered QR code:

Check destination URLs against the expected domain before proceeding:

from urllib.parse import urlparse

def is_expected_domain(url, expected):
    parsed = urlparse(url)
    return parsed.netloc.endswith(expected)

print(is_expected_domain("https://parking.cityname.gov/pay?lot=42", "cityname.gov"))
# True

print(is_expected_domain("https://parking-cityname.com/pay?lot=42", "cityname.gov"))
# False — phishing attempt

Creating Privacy-Respecting QR Codes

If you create QR codes, use direct URLs without tracking parameters:

# Generate a QR code from a URL (offline)
sudo apt install qrencode
qrencode -o myqr.png "https://yoursite.com/page"

# Or text
qrencode -o contact.png "BEGIN:VCARD\nFN:Your Name\nTEL:+1234567890\nEND:VCARD"

# High resolution for print
qrencode -s 10 -o print.png "https://yoursite.com"

Do not use URL shorteners (they add a tracking layer), UTM parameters (tell your analytics server who scanned), or third-party QR management platforms (they own the redirect data).

Advanced QR Code Attacks: Beyond Tracking

QR codes can be weaponized in ways beyond simple tracking:

1. Malware Distribution

Physical QR code → Shortened URL → Malicious APK download

Example:

Defense:

2. Exploit Chains

Attackers chain QR code endpoints for multi-stage attacks:

https://bit.ly/parking →
https://redirector.site/123?token=xyz →
https://phishing-site.com/?redirect_token=xyz&user_id=<YOUR_IP>

Each redirect layer extracts information and forwards you to the next. By the time you reach the destination, the attacker knows:

3. NFC-to-QR Hybrid Attacks

Some QR codes trigger NFC actions when scanned:

QR code + NFC tag → Opens app + starts Bluetooth connection
→ Connects to attacker-controlled Bluetooth device
→ Exfiltrates nearby device list or phone number

Mitigate by:

QR Code Tracking at Scale

Governments and corporations use QR codes for population-level tracking:

China’s “Health Code” System:

Parking Payment QR Codes:

Product QR Codes:

If you see QR codes everywhere, assume each one is a tracking opportunity. Decode before scanning.

Building QR Code Awareness

Train your organization to avoid dangerous QR code practices:

For employees:

  1. Decode QR codes before opening them (don’t blindly scan)
  2. Check the domain in the decoded URL — does it match the expected service?
  3. Report suspicious QR codes to IT/security
  4. Never scan QR codes from public restrooms, elevators, or unusual locations

For your website/service:

  1. If you generate QR codes, use direct links (no UTM parameters, no shorteners)
  2. Include text near the QR code with the expected domain (e.g., “Scan to visit example.com”)
  3. Don’t use URL shorteners — the redirect layer is an attack point
  4. Rotate QR codes regularly (monthly, not quarterly)
  5. Monitor clicks from QR codes using a dedicated endpoint (not your general analytics)

QR Code Forensics: If You Suspect Compromise

If you scanned a suspicious QR code and worry about consequences:

# 1. Check browser history for unexpected redirects
# Open: history > search for the date you scanned

# 2. Review recently installed apps
# Settings > Apps > Sort by "Install Date"

# 3. Check recent network connections (on rooted device)
adb shell netstat -tlnp 2>/dev/null | grep ESTABLISHED

# 4. Monitor battery drain (suggests background activity)
adb shell dumpsys batteryexplained | grep "Uid" | head -10

# 5. Check system logs for error messages
adb logcat | grep -i "crash\|error\|malware" | tail -20

If you suspect real compromise:

  1. Enable Safe Mode (suppresses third-party apps)
  2. Install Malwarebytes on Android (detects common payloads)
  3. Use a network monitor app (e.g., NetGuard) to see what’s connecting
  4. If confident it’s malware, factory reset the device

QR Code Privacy Legislation

Some jurisdictions are restricting QR code tracking:

GDPR (Europe):

CCPA (California):

Australia (Privacy Act):

If a QR code is placed on property you control and it tracks users, you may have legal obligations to disclose this. Consult a privacy lawyer if you operate public QR codes.

Alternative to QR Codes: Direct URLs

QR codes are convenient but privacy-invasive. Alternatives:

Instead of QR code:
https://bit.ly/parking-pay

Use:
Direct URL on sign: "Pay at parking.cityname.gov"

Benefits: