Skip to content
UseQR
ESC

↑↓ MOVE↵ OPEN48 PLACES

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.

View as MarkdownPaste this page into any AI assistant — it is plain, portable Markdown.

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

  • How to change what a QR code points toThe 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 toolPoint 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 codesA 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 functionsGenerating QR codes in Lambda, Cloudflare Workers and Vercel functions — bundle size, native dependency pitfalls, streaming, and when to skip the function entirely.