Step 1: Decoding, entirely on your device
When you upload an image or use the live camera scanner, the QR code is decoded directly in your browser — for uploads via the jsQR library, for live camera scanning via your browser's native barcode-detection APIs. The image itself is never uploaded to our servers. Only after decoding, and only if the decoded content is a web link, does anything get sent anywhere.
Step 2: Bot verification
Before any check runs, your browser completes a Cloudflare Turnstile challenge — an invisible, automatic verification that confirms the request is coming from a real browser rather than an automated script. This runs silently in the background for legitimate visitors; you shouldn't notice it happening.
Step 3: Redirect resolution
A shortened or redirecting link isn't itself malicious or safe — the page it actually lands on is. Before checking or caching anything, our server follows the link's redirect chain (up to 5 hops, with a timeout) to find the real final destination. That final destination — not the link you scanned — is what actually gets checked and cached. If a redirect chain leads somewhere different from what was scanned, both the original link and the final destination are shown in your result.
Some redirects depend on JavaScript running in a full browser rather than a simple server request, or vary based on who's asking (a technique some attackers use specifically to evade automated scanners). Our redirect resolution catches standard HTTP redirects reliably; it won't catch every possible evasion technique.
Step 4: The threat-intelligence check
The final destination is checked against Google Web Risk, a threat-intelligence database of confirmed phishing, malware, and unwanted-software sites, maintained by Google's own security infrastructure. We check against three specific threat categories: SOCIAL_ENGINEERING (phishing), MALWARE, and UNWANTED_SOFTWARE.
Step 5: Verdict mapping
The raw threat categories get mapped to the plain-language verdicts you actually see:
- Clear to Scan — no threat categories matched.
- Hold — Verify — flagged only for UNWANTED_SOFTWARE (deceptive but not outright malicious software).
- Do Not Scan — flagged for MALWARE and/or SOCIAL_ENGINEERING (phishing).
- Unverified — the check itself failed (network error, timeout, or the destination pointed to a private/internal address that can't be safety-checked).
When a destination is flagged, the specific reason (e.g. "phishing" or "malware distribution") is shown directly in your result — not just a generic warning.
Step 6: Caching
To keep the service fast and free at scale, results are cached by destination URL. A confirmed verdict (safe, suspicious, or malicious) is cached for 24 hours. An "Unverified" result — which usually means a transient failure, not a real finding — is cached for only 10 minutes, so a temporary glitch doesn't stay wrong all day. This also means: if you check the exact same link twice within a short window, the second check may return a cached result rather than a fresh one.
What this system can't do
- It can't catch brand-new threats instantly. Threat-intelligence databases are updated continuously but not instantaneously — a scam page live for only a few hours may not yet be flagged anywhere.
- It doesn't render or execute the destination page. The check is based on the URL and Google's existing intelligence about it, not a live simulated visit that inspects the page's actual content.
- It only checks web links. QR codes containing Wi-Fi credentials, contact cards, or plain text have no destination to check — we simply show you what's decoded.
"Clear to Scan" means "not currently flagged" — a strong signal, not a certainty. Stay cautious with anything asking for a password or payment, regardless of the verdict.
Change log
- September 5, 2026 — Added redirect-chain resolution (destinations are now checked and cached by final URL, not the originally scanned link) and specific reason codes shown alongside flagged results.
- August 2026 — Initial launch: client-side decoding, Google Web Risk integration, Turnstile bot protection, KV-based caching and rate limiting.