How-to guides
How to make one QR code do different things by device
Encode a single URL on a domain you control and branch there: the server or a small script inspects the user agent and redirects iPhones to the App Store, Android to Play, and everyone else to a landing page. It works, but the redirect must stay alive as long as the print does.
The architecture: one code, one URL, one branch point
A QR code cannot detect devices — it is inert data. The branching happens at the URL it opens. So the pattern is always:
One printed code → https://example.com/get → inspect User-Agent → redirect
The classic use is app distribution: one code on the poster, iPhones land on the App Store, Android lands on Google Play, laptops land on a page with both badges. The same mechanism serves platform-specific deep links, OS-specific help pages, or mobile-vs-desktop experiences.
Client-side version (simplest to deploy)
A static HTML page at the encoded URL, a few lines of script:
<script>
var ua = navigator.userAgent;
if (/iPhone|iPad|iPod/.test(ua)) {
location.replace("https://apps.apple.com/app/id0000000000");
} else if (/Android/.test(ua)) {
location.replace("https://play.google.com/store/apps/details?id=com.example.app");
}
// no match: stay on this page, which shows both store badges
</script>
Falling through to a visible page with both buttons is the load-bearing detail — it is your safety net for everything the sniffing gets wrong.
Server-side version (cleaner)
A 302 issued by the server — a redirect rule, an edge middleware, or a tiny serverless function — avoids the blank flash of the client-side page, works with JavaScript disabled, and gives you a log line per scan, which is free analytics into the bargain. Same logic, same fallback: anything unmatched gets the landing page, not a guess.
The honest caveats
- User-agent sniffing is approximate. The canonical trap: iPadOS Safari requests desktop sites by default and identifies itself like a Mac, so naive rules send iPads to your desktop page instead of the App Store. Treat misclassification as normal and let the fallback page absorb it.
- You are now running a redirect service. The printed code is only as alive as
example.com/get. That endpoint must survive redesigns, replatformings and staff changes for the life of the print — the same permanence contract discussed in changing what a code points to. - Hosted "smart link" products carry platform risk. Third-party device-routing services exist, but you inherit their lifespan: Google's Firebase Dynamic Links — once the standard answer here — was shut down in 2025. Ten lines on your own domain have no such expiry; the general argument is in static vs dynamic.
For the common app-install case, start from the app download QR generator; for anything custom, encode with the URL generator and confirm the final payload in the validator. Then test the full matrix before printing: an iPhone, an Android phone, an iPad (it will surprise you), and a laptop.
FAQ
Can a QR code detect what phone scanned it?
No — the code is static data. The detection happens at the URL it opens, where a server or script inspects the browser's user agent and redirects accordingly.
How do I make one QR code open the right app store?
Encode a URL you control; at that URL, redirect Apple devices to the App Store, Android to Google Play, and show everyone else a page with both badges. The fallback page catches every device the rules misread.
Why does my iPad get the wrong destination?
iPadOS Safari requests desktop websites by default and presents a Mac-like user agent, so simple rules classify iPads as desktops. Design the fallback page to serve them well rather than fighting the user agent.
Is there a service that does device routing for me?
Several exist, including dynamic QR platforms — but the printed code then depends on their continued operation, and such services do shut down. A short redirect on your own domain does the same job without an expiry date you don't control.
Try it — free, no signup
Related
- How to change what a QR code points to — The modules are the data — a printed static code can't be re-encoded. Your real options: change a redirect you control, reprint, or plan dynamic next time.
- How to track QR code scans without a paid tool — Point the code at a URL on your own domain carrying UTM parameters, and read the results in your own analytics. That gives you scan counts, timing and…
- Static vs dynamic QR codes — A static QR code contains its destination directly, so it never expires and cannot be tracked or edited. A dynamic code contains a short link that…
- QR codes in serverless functions — Generating QR codes in Lambda, Cloudflare Workers and Vercel functions — bundle size, native dependency pitfalls, streaming, and when to skip the function entirely.