Privacy & compliance

How to track QR scans without breaking the GDPR

Paolo Matias Tonello7 min read

Every dynamic QR code scan is an HTTP request, and every HTTP request carries a small bundle of data about the device that made it — the question is not whether you can measure scans, but what you do with that bundle once it arrives.

What a scan request actually exposes

When a phone camera reads a dynamic QR code, it opens the encoded short link in a browser, which sends a standard HTTP GET request to the redirect server. That request includes the IP address of the device, the User-Agent string, an optional referrer header, and a timestamp recorded by the server.

None of this requires JavaScript, a cookie or an app. It is the same information any web server sees on any page load, and it is enough to derive a country, a device type, an operating system and a browser family without ever asking the user anything.

  • IP address: used momentarily to resolve a country, then discarded or truncated
  • User-Agent: parsed into device type, OS and browser, then discarded
  • Referrer: shows whether the scan came from a QR code, a shared link or an app
  • Timestamp: recorded to build scan-volume-over-time charts

Why an IP address counts as personal data

Under the GDPR, an IP address is personal data because it can, in combination with other information available to an internet service provider, be linked back to an individual. This holds even for dynamic IPs and even if you never intend to identify anyone. Courts and data protection authorities across the EU have treated IP addresses as personal data for over a decade.

The practical consequence is not that you cannot use IPs at all — it is that you cannot store the raw address without a clear legal basis, a retention limit and a documented purpose. The safer and simpler route is to avoid storing it in the first place.

  • Resolve the IP to a country at request time, then discard the address
  • If finer geolocation is needed, truncate the last octet (or the equivalent IPv6 block) before any logging
  • Never write raw IP addresses to long-term logs, exports or analytics tables
  • If a raw IP must be kept briefly for security (fraud, abuse), cap retention to days, not months

Cookieless measurement and when you need a consent banner

The ePrivacy Directive's Article 5(3) requires consent before you store or access information on a user's device — that is what triggers a cookie banner, not analytics in general. If your redirect sets no cookie, writes no identifier to local storage and drops no tracking pixel, you are not storing or accessing anything on the device, so Article 5(3) simply does not apply to that scan.

What you are left with is server-side counting: incrementing an aggregate counter for a given QR code, tagged with a derived country, device type, browser and referrer. No per-user identifier is created, no cross-session linking is possible, and nobody's device is touched. That is the model Qreator's dynamic redirects use: a scan on /r/<code> increments a counter and records derived breakdowns, sets no cookie, and never stores the raw IP.

Counting how many times a QR code was scanned, broken down by country and device, is typically justifiable under legitimate interest: it is a modest, expected, non-intrusive processing activity that helps you understand which flyer or poster performed better, and it does not meaningfully affect the individual who scanned the code.

The moment you attach an identifier to a specific person — a unique code per named recipient, a login-linked scan, a device fingerprint used to recognise repeat visitors — you have moved into profiling territory, and legitimate interest is a much weaker footing. At that point you need explicit consent, a documented balancing test, and usually a more detailed privacy notice.

Data point exposed by a scan and how to treat it
Data pointPersonal data?What to keep
Raw IP addressYesNothing — resolve to country, then discard
Country derived from IPNo (aggregate)Keep as a count per QR code
User-Agent stringBorderlineParse into device/OS/browser, discard the raw string
Referrer headerNo, if not combined with an identifierKeep as an aggregate source label
TimestampNo, on its ownKeep for volume-over-time charts
Unique code per named personYesOnly with consent or a clear notice to that person

Data minimisation, retention limits and purpose limitation

Three GDPR principles do most of the work here. Data minimisation means you collect only what the stated purpose needs — for 'how many scans did this poster get', that is a counter and a country, not a raw IP. Purpose limitation means you do not repurpose scan data collected for campaign measurement into something like individual profiling later. Storage limitation means aggregate counters can reasonably be kept indefinitely because they are not personal data, but anything closer to raw request logs should have a defined, short retention window.

Write these choices down. A one-paragraph internal note describing what you collect, why, and for how long is usually enough to demonstrate accountability if a data protection authority ever asks.

What to write in the privacy notice, and where to link it

Even cookieless, aggregate measurement should be disclosed. A short paragraph naming what is collected (country, device type, browser, referrer, scan timestamp), confirming that no cookie is set and no raw IP is retained, and stating the legal basis (legitimate interest) is enough for most campaigns.

Link that paragraph from wherever the code is displayed when practical — a small line on the printed material, or in the destination page's own privacy policy if the code redirects to your site. If the code sits on packaging with no room for text, keeping the notice on the landing page it redirects to is an acceptable fallback.

Pitfalls that reintroduce compliance work

A cookieless redirect does not make everything downstream cookieless. If your destination page loads a third-party analytics script, an ad pixel or a chat widget, that page now sets cookies or writes to local storage, and Article 5(3) consent duties apply to that page — regardless of how clean the QR redirect itself is.

Similarly, adding UTM parameters to the destination URL does not by itself create a privacy problem — UTM parameters are just query strings, visible in the address bar. The risk appears only if the destination site's analytics tool uses those parameters to build a profile and does so without consent. That is the destination owner's responsibility to solve, not something the QR code layer can fix for them.

International transfers and the processor relationship

If the service hosting your redirects or analytics is based outside the EU/EEA, storing even aggregate, non-identifying data there generally raises fewer questions than personal data transfers, but if you do retain any personal data (support logs, account data, raw IPs during a short debugging window), check that the provider has an adequate transfer mechanism such as Standard Contractual Clauses.

Whoever operates the QR redirect infrastructure on your behalf is typically your data processor, and you remain the controller responsible for the purpose of processing. A data processing agreement (DPA) with that provider is standard practice and usually available on request.

What not to do

  1. Do not generate a unique QR code per named recipient (e.g. per invitee on a mailing list) without telling that person their individual scan will be recorded
  2. Do not use device fingerprinting to recognise the same visitor across sessions without consent
  3. Do not chain the redirect through a third-party tracking pixel or ad network before reaching your destination
  4. Do not store raw IP addresses in exports, CSVs or backups 'just in case'

Author

Paolo Matias TonelloFounder, Qreator

Founder of MT Digital Services LLC and builder of Qreator. Writes about QR codes, print production and privacy-friendly analytics.

Put it into practice