Privacy Policy

Last updated: 21 October 2026

Summary

Shooter is an offline-first scoring app. Your matches, scores, and hole positions stay on your device. Your target photos do too, with one exception you control: if you turn on Share target photos, the photo of a target you score may be uploaded to our servers — to be scored by AI, and/or kept to improve our on-device detection. We collect a small amount of pseudonymous diagnostic data — tagged with a random device identifier, never your name — to fix bugs and improve the product.

What stays with you

  • Your shooting history stays on your device
  • No account, no sign-up, no email required
  • No advertising, no tracking across other apps or websites
  • Photo upload is one opt-in — the app asks once, and you can change your answer at any time with the Share target photos toggle in Profile → Privacy & terms

What leaves the device

  • With Share target photos on, the photo you are scoring is uploaded and may be stored (see below for exactly what happens to it)
  • Pseudonymous crash reports and product analytics are collected (see below)

If you only read one section, read Third parties at a glance.


Who we are

Shooter is an iOS and Android app for scoring paper shooting targets, operated by Shooter Team. You can reach us at shooter.support@gmail.com.


What stays on your device

By default, the following data lives only in your device's local storage and never reaches our servers:

  • Every match, session, series, and individual shot
  • Computed scores, ring values, MPI, mean radius, sight adjustments
  • Photos you take of paper targets — unless you score one with AI, or choose to contribute one (both covered under What you choose to share)
  • App preferences (theme, default discipline, custom badges, etc.)
  • Your shooting history across all time

You can export this data through the app's backup feature, or delete it by clearing the app or uninstalling it.


What we collect automatically

The following data is sent off your device automatically when you use the app.

Random device identifier

The first time you use the app, the app generates a random device identifier — a UUID, minted on your phone and stored in your device's secure keychain. It contains no personal information and is not derived from your Apple ID, Google account, email address, phone number, or any other identifier you use elsewhere. Because it is stable for as long as you use the app, the data keyed to it is pseudonymous rather than anonymous: it identifies your device across sessions without telling us who you are.

It is not the account identifier. Our server keeps its own, different identifier for your account (the users row id). That one is what analytics and crash reports carry, and only we can join the two. The device identifier is what your phone presents, when it pairs with our server, so that a reinstalled or new phone finds the account it already had.

Attestation is a separate thing. The app also proves to our servers that it is a genuine, unmodified copy of Shooter, using Apple App Attest (iOS) or Google Play Integrity (Android). That check answers "is this really our app?"; the identifier above answers "is this the same device as last time". Neither attestation service generates the identifier, and no attestation-derived identifier is kept on Android.

We use it to:

  • Authenticate that requests come from a legitimate copy of the app
  • Bind subscriptions to your device
  • Count free-tier scans against quota
  • Tag crash reports and analytics events so we can spot patterns within a single user without knowing who that user is

The identifier is stored in your device's secure keychain and as a row in our users table on the server. We have no way to map it back to you personally.

Free scans — Apple DeviceCheck (iPhone only)

On an iPhone the app keeps one yes/no flag for your phone at Apple, using Apple DeviceCheck: "this device has used up its free scans". When you use your last free scan the app asks our server to set the flag, and when it is given back (a failed scan) to clear it; on launch, if you are not a Pro subscriber and still have free scans left, the app asks our server to read it, and counts your scans as used if Apple says so. Our server makes these calls to Apple with a token your phone mints, and stores nothing from them. The flag is held by Apple against the phone, not against your Shooter data: it survives reinstalling the app, and Delete my data does not reset it — that is what it is for, since otherwise reinstalling would hand out the free scans again. Android has no equivalent, and nothing is sent there.

Crash reports and diagnostics — Sentry

We use Sentry to collect crash reports, runtime errors, and a limited set of breadcrumbs (recent in-app events that led up to a crash). This helps us fix bugs without asking you to report them.

Each report includes:

  • The stack trace and exception message
  • App version, OS version, device model
  • The account identifier our server knows your device by — the users row id, not the device identifier itself (the two are one-to-one on our side, and only we can join them)
  • A small set of context tags (the feature that crashed, e.g. backup-restore, attestation, insights)

When you send feedback yourself from Profile → Send feedback, that one report also carries your purchase identifier (the Support ID row's value), so we can act on a purchase problem without asking you to look it up. It is attached to that report only, never to automatic crash reports, and not at all if you have turned off Link usage data.

That same form has an optional email field. It is the only place in the app that asks for an email address; it is never pre-filled, leaving it empty sends the report anyway, and we use it for exactly one thing — replying to you about that report. The text you write in the message box is sent with it, so please don't put anything in there you would not want us to read.

Reports do not include the contents of your shooting data or your photos — local file paths are scrubbed before anything is sent.

Crash reporting is always on: we process these minimal, pseudonymous reports under our legitimate interest in keeping the app working (see Legal bases below). If you turn off Link usage data in Profile → Privacy & terms, crash reports keep flowing but are no longer tagged with your device identifier — they arrive anonymous. You can object to crash-report processing entirely by contacting us (see Your rights).

Product analytics — PostHog

We use PostHog to understand how the app is used in aggregate. Events tell us things like "user opened the paywall", "user completed a scan", or "user picked discipline X". Each event includes the same account identifier Sentry gets — the users row id our server assigns, not the device identifier itself — and a small set of properties, never the contents of your scans, sessions, or photos.

We use this to:

  • Decide which features to invest in
  • Spot regressions (e.g. a sudden drop in completed scans suggests a bug we introduced)
  • Measure how well onboarding performs

Analytics events are routed through Cloudflare on their way to PostHog, via PostHog's managed reverse proxy — a routing layer that Cloudflare operates on PostHog's behalf. Cloudflare only handles the transport of these events (the same account identifier and usage-event properties described above; never the contents of your scans, sessions, or photos) and may process that traffic from multiple or dynamically-assigned geographic locations as part of routing it onward. PostHog itself is configured to store data on its EU servers: events are routed via Cloudflare's global edge in transit, then stored on PostHog's EU infrastructure. PostHog does not perform cross-app or cross-site tracking and only sees activity inside our app.

Turning off Link usage data in Profile → Privacy & terms does not stop these events — it de-identifies them. With the switch off: events keep sending over the same Cloudflare-routed path (so we can still see aggregate feature usage and catch regressions), but no longer carry your device identifier, no profile is built for you, and PostHog assigns a random identifier that starts over every time you open the app — so events can't be tied to your identity or linked across sessions. The switch takes effect immediately and survives restarts.

Import mapping votes

If you import your history from another scoring app (e.g. TargetScan), the app reports which of our targets you mapped each imported discipline to. Each vote consists of a fingerprint of the imported discipline's scoring shape, the target you picked, TargetScan's app version and backup version (read from the backup file), and — if Link usage data is on — your random device identifier (used only so repeat imports from the same device don't inflate the count). We tally these votes on our side to see which target an imported discipline most likely corresponds to; nothing is sent back to the app, which does not fetch suggestions. No shooting data, scores, or photos are included.

If Link usage data is off, votes are stored without the device identifier. Because the vote then carries no identifier for us to de-duplicate against, the app itself keeps a small local record of what it has already reported so re-importing the same backup doesn't send (or count) the same vote twice.

Detector measurements

When you save a scored target, the app may compare what its on-device detector found with the shots you saved, and send us only the result as four numbers: how many shots you saved, how many holes the detector found, how many of those match your shots, and how many of those score the same ring. The report also names the target, whether the photo held one target or several (a strip of targets, say), the app's and the detector's versions and a random id for the scan, and — if Link usage data is on — your random device identifier, so that one device's scans count as one shooter. It contains no photo, no shot positions and no scores. We use these numbers to decide automatically which targets the app can score offline — for photos of one target and photos of several separately — and to switch a target back to AI if the detector does poorly on it.

Your IP address

Every request your phone makes to our servers carries your IP address, because every internet request does. Under the GDPR an IP address is personal data, so we name it here rather than describe the request as if it had no sender.

We use it for one thing: rate limiting. Each of our endpoints counts recent requests per address, in a short-lived sliding-window counter in our rate-limit store, so one network cannot flood an endpoint that costs us money or capacity. The counter expires on its own within minutes. We do not write your IP address into our database, do not attach it to your device identifier, your photos, or your shooting data, and do not use it to locate you. Legal basis: our legitimate interest in keeping the service available and affordable (see Legal bases below).

The third parties in the table below necessarily see the IP address of the connection your phone or browser makes to them, and handle it under their own policies.


What you choose to share

These categories of data leave your device only when you actively opt in.

Target photos — one consent for AI scoring and detector training

Photo upload is governed by a single opt-in. After one of your first scans, the app asks a yes/no question: whether photos of the targets you score may be uploaded. You can dismiss or decline it, and you can change your answer at any time with the Share target photos toggle in Profile → Privacy & terms (help text in the app: "Required for AI scoring — the photo is sent to be scored. Some photos are also kept to improve offline detection, until we have enough for that discipline.").

This one consent covers both things a photo upload can be used for:

  • AI scoring — for targets our on-device detector has not yet been trained on, the photo is sent to an AI vision service that locates the shot holes (details in AI-powered scoring below).
  • Detector training — the photo may be stored on our servers (getshooter.app) and used to evaluate and improve our on-device hole-detection models, so more paper variants can be scored fully offline.

Which of the two happens for a given scan depends on the target and on upload caps — some photos are AI-scored, some are only collected for training, some are both. In every case:

  • The photo is associated with your random device identifier — it is stored without your name, but it is linked to your device until you ask us to unlink it (see Your rights)
  • We do not publish, sell, or share the photo with third parties (beyond the AI sub-processors named in Third parties at a glance, and only for AI-scored photos)
  • If the toggle is off, or you decline the question, no photo ever leaves your device — the app scores everything with its on-device detector only

AI-powered scoring (opt-in)

For targets our on-device detector has not yet been trained on, the app may score the target with AI instead. AI scoring runs only under the single photo-upload consent described above (the Share target photos toggle) — it is not a separate permission. If you have declined or turned the toggle off, nothing is sent or stored, and the app falls back to its on-device best-effort scoring.

When an AI scoring runs:

  • The target photo is sent to an external AI vision service — accessed through the Vercel AI Gateway — which returns the positions of the detected shot holes. We then score those positions with our own scoring rules on our servers. We may change which AI provider we use over time; the Third parties at a glance table below always names the current one.
  • The photo and the AI-generated annotations are stored on our servers (getshooter.app), associated with your random device identifier, and used to review the result and to expand the range of targets we support.
  • The photo and annotations are not published, sold, or shared with any third party beyond the AI sub-processors named in the table below.
  • Some AI analyses are paid for with AI credits — one-time consumable purchases verified through RevenueCat (see below). A credit is used when an analysis completes, and is refunded if the analysis fails; an analysis that completes but finds no shot holes counts as completed, so its credit is not refunded. AI scoring is otherwise also rate-limited per device, per day. We keep a small technical record of each request (the model used, token counts, cost, and timing) for billing and abuse prevention; it is not used to identify you. There is no automatic expiry on these records today — we delete them by hand when we no longer need them, and we would rather say so than quote a retention period nothing in the system enforces. Asking us to delete your data unlinks these records from your identifier immediately (see Your rights).

You can ask us to unlink photos and AI annotations from your device identifier at any time (see Your rights). Unlinking removes the connection to your device; the photo itself may remain in the training corpus, no longer tied to anyone.

Purchases — RevenueCat

The app sets RevenueCat up on every launch, whether or not you ever buy anything — it has to, because that is how the app learns that you already own Pro or have credits left. So RevenueCat receives your purchase identifier (the random id described under "Three identifiers" below) from every install, along with your platform and app version, even from a device that never makes a purchase. That is the one thing on this page that happens without a purchase and without a toggle; we would rather you read it here than discover it in a network trace.

If you then buy a subscription or a pack of AI credits, we use RevenueCat to verify and manage the purchase. RevenueCat additionally receives your platform purchase token (the same one the App Store or Play Store issues) and the product identifier.

Our own server also receives the purchase identifier: at every launch, and when you return to the app (at most every ten minutes), the app posts it to getshooter.app/api/credits to recover any credit pack the store charged for but that was never delivered, and our server records that the identifier belongs to your account so that a renewal or cancellation reaches the right account. When there is nothing to recover this changes nothing, but the request is still made.

For AI credits specifically, our server keeps an append-only ledger of credit purchases and consumption, keyed to the RevenueCat transaction id for that purchase — we re-verify each purchase against RevenueCat's API and retain the transaction id as our record of that verification.

RevenueCat does not receive your name, email, address, or payment card. Those stay with Apple or Google.

Three identifiers kept in your own cloud account

Separately from the backups below, the app stores three short identifiers in the small key-value area your phone's operating system reserves for values that should follow the person rather than the handset: iCloud key-value storage on iOS, Google Block Store on Android. Unlike a backup, this happens automatically rather than when you choose it, which is why it is described here. The check-in code is written when it is created; the other two are not written the moment they are created, but later — the purchase identifier on a later launch, the device identifier the next time the app pairs with our server — so that a new phone's first launch cannot overwrite an identifier still on its way from iCloud.

  • Your check-in code — the six-character code a club's attendance register matches you on. It is created once and never regenerated, so if a new phone could not find it you would silently become a different person in every register that already holds the old one.
  • Your device identifier — the random device identifier described above, which is what a new phone uses to find the account that already belongs to you. Without it a phone change would create a fresh, empty account, and any AI credits you had bought would stay behind on the old one.
  • Your purchase identifier — the random id RevenueCat knows your purchases by. Carrying it means a new phone simply is the customer who bought Pro, rather than having to reclaim the purchase afterwards.

This is what makes a new phone on the same platform work without you doing anything. It does not cross between iOS and Android — Apple and Google keep separate stores and separate accounts — so switching platform means buying Pro again; see the Terms of Use and the support page for what happens to your credits.

All three are random values that identify nobody by themselves. None of them carries your name, and no shooting data, photos, or scores go into this area. It lives in your own iCloud or Google account, not on our servers — we cannot read it, and it is removed when you delete the app's data from that account (iOS: signing out of iCloud or turning off iCloud for the app; Android: Settings → Google → Backup).

Cloud backups — your own iCloud Drive or Google Drive

The app can back up your shooting data to your own cloud account: iCloud Drive on iOS, Google Drive on Android. Backups are created only when you choose to make one, and the backup file goes directly from your phone to your cloud account — it never passes through or reaches our servers, and we cannot see it.

  • iOS: backups are stored in the app's folder in your iCloud Drive, on your iCloud storage quota. You can see and delete them yourself in the Files app.
  • Android: the app asks you to sign in with Google (OAuth) and requests only the narrow drive.appdata permission — access to a hidden, app-private folder in your Google Drive. It cannot read the rest of your Drive. You can revoke access or delete the app's data at any time from your Google Drive settings (Settings → Manage apps).

A backup does not contain your own name — that is the one thing left out of it. Your check-in code travels in it, because that is what keeps a club's record of you intact across a phone change, but the name attached to the code does not, so the file does not put a name and a code side by side. The app asks for your name again the first time you present the code after a restore.

Everything else in the app's database is in the file, and two parts of it are worth naming:

  • Your guns as you entered them — including the licence numbers, weapon IDs, and licence renewal dates you recorded. Those never leave your phone over the network, and only a one-way code derived from them is ever shared with a club (see below), but the backup is a copy of your own data, so the numbers themselves are in it.
  • Your club register, if you run club sessions — the attending shooters' names, the weapons they declared, and when they checked in. A register without names would not be a register, and it is the reason club devices back up at all.

Unless you switch off Include app settings when you make it (it is on by default), the file also holds the app's whole settings file: for example your language and region, birth year if you entered one, handedness, the targets you favourited or picked as yours, licence and activity thresholds, and your Share target photos and Link usage data choices.

Treat the file accordingly: it goes to your own cloud account and never to us, but anyone you hand a copy to gets those contents.

You can also delete individual backups from within the app (Profile → Data & transfer). Because backups live in your own cloud account under your control, they are not covered by our server-side retention or deletion mechanics — deleting them is entirely in your hands.

Your phone's own device backup

Separately from the backups above, which you choose to make, your phone's operating system backs the app up automatically as part of backing up the whole device: iCloud Backup on iOS, Google One / Auto Backup on Android. On iOS that copy contains the app's whole storage folder as it sits on the phone — the database, the settings file, the backups you made on the phone, and also any target photos still queued for upload under pending-uploads/, which the deliberate backup does not include. Android's copy is the same folder with two things left out — the app's own backups/ folder (copies of data the database already holds) and a small file used while a purchase identifier is first being stored — and the values in the app's secure storage (where the random device identifier and the purchase identifier are kept) are left out of the Android copy as well.

The difference between the two is narrower than it sounds, and it is worth being exact about. The register and your own licence and firearm details are in both files; the device backup is not special for holding them. What separates them is your own name: the file you make from Profile → Data & transfer leaves it out, and the operating system's copy does not, so the device backup is the one that pairs your name with your check-in code.

It never reaches us. It lives in your Apple or Google account, is protected by that account's own security rather than by anything the app does, and is deleted by turning the app's backup off in your device's settings (iOS: Settings → [your name] → iCloud → Manage Storage; Android: Settings → Google → Backup). We are describing it here because it happens without you asking, and because if you run a club's register on a shared phone it is worth knowing that other people's names are in that account's backup.


What we fetch from our servers

A few small reads go in the opposite direction — from our servers to your app.

  • Analysis and drill copy: The training advice shown on the Analysis screen is fetched from admin.getshooter.app/api/public/coach/latest. This is a public catalogue, the same for everyone — it carries no device identifier and nothing about your shooting. It is not quite a blank request, though: like every call the app makes to our own servers, it sends your app version, build number, and platform (so we can tell which versions are still out there and keep serving them), plus an ETag of the copy you already hold, so an unchanged catalogue costs a 304 instead of a download. The result is cached on your device for 24 hours.
  • Subscription status: When you complete an upload or restart the app, we may refresh your subscription/quota status from getshooter.app/api/me.
  • Minimum version: the app reads a small public file, getshooter.app/shooter-min-version.json, to learn whether this version is still supported, at most once an hour (the answer is kept on your phone). It is the same for everyone and carries no device identifier.
  • Newer version in the App Store (iPhone only): the app asks Apple's public lookup service (itunes.apple.com) whether a newer version of Shooter is out, at most every six hours. The request names the app and your phone's country code (from its region setting), so Apple sees it as any request, with your IP address; it goes to Apple, not through us.
  • Over-the-air updates: The app does ship over-the-air JavaScript updates, through Expo's EAS Update service, and checks for one each time you launch it. The check and any download it triggers carry a persistent random client identifier that Expo's updates library generates (EAS-Client-ID), along with your app version and platform — so Expo can be told which build to serve you. It is a separate identifier from the one this policy describes elsewhere, it is not joined to your device identifier, and no shooting data, photos, or analytics ride along with it. The update itself is application code, the same for every device on that build.

Web pairing (getshooter.app/submit)

The app does not currently offer this: there is no way to start a pairing from the app's screens. The web pages and the pairing service are still online, and what follows is what they do.

If you use the browser upload flow at getshooter.app/submit, your browser is paired with your phone using a short code (or QR code) shown on screen. Pairing codes are short-lived — they expire after about five minutes if unused. A successful pairing creates a browser session that is valid for about one hour, after which you simply pair again. The session is linked to the same random device identifier described above; pairing involves no account, email, or other personal information.


Website cookies and analytics

The getshooter.app website sets no cookies. It reports its own errors, and it is measured in two ways, only the second of which needs your permission.

Always on, without cookies: Vercel Web Analytics and Speed Insights. Vercel, the US company that hosts the website, counts page views and measures how fast pages load. Nothing is stored in your browser and no identifier follows you: Vercel tells visits apart only by a hash it derives from each request, which is discarded after 24 hours. Each page view records the page address, the site you came from, your approximate location (country, region and city, worked out from the request; your IP address is not stored), your browser, operating system and device type. Speed Insights adds the page's load-time measurements (Core Web Vitals) and your network speed class (for example "4g"). We see all of it only as aggregate numbers, never as a trail of one visitor. The pairing code in a getshooter.app/pair/… address is removed before anything is sent.

Only if you choose: PostHog. On your first visit a consent banner asks whether we may enable it:

  • Decline (or dismiss the banner with Escape): PostHog is never loaded, and nothing is stored beyond your "declined" choice. Only the cookieless Vercel measurement described above runs.
  • Accept: the site loads PostHog web analytics (the same product-analytics service the app uses, with the same EU storage), which measures how the site is used: the pages you visit, the links and buttons you click and where on the page, how far down a page you scroll, and how fast pages load. It makes no recording of your screen. It keeps a random identifier in your browser's local storage, so it can tell a returning visitor's page views apart, and like every website it receives your IP address with each request. PostHog does not track you across other websites.

Always on: error reports to Sentry. When something on a page breaks, the website sends Sentry a report: the error and the code it came from, the page address, and your browser and operating system. It records no page views and no session, stores nothing in your browser, and runs on legitimate interest (keeping the site working) whether or not you accept analytics. Like the app's crash reports, the reports are deleted after 90 days.

Your choice is stored in your browser (local storage) so the banner doesn't reappear, and you can change it at any time by clearing the site's browser data. The app itself uses no cookies — the sections above describe everything the app sends.


What we do NOT collect

  • We do not collect your name, phone number, or postal address, and there is no account to create
  • We do not ask for an email address anywhere except the optional field on the feedback form described above — nothing in the app collects one in the background, and you can send feedback without filling it in
  • We do not access your contacts, photo library (beyond the photos you explicitly take or pick for the app), calendar, or location
  • We do not advertise. We have no advertising SDK installed.
  • We do not track you across other apps or websites
  • We do not sell any data, ever

If you use club attendance, presenting your check-in code shares the following directly with a club's device: the first and last name you enter, the check-in code itself, the app's own id for each weapon you tick, the name you gave that weapon and its weapon group, a one-way code for each licence number and weapon ID you have recorded against it, and, on an iPhone that has one, the identifier of the App Attest key your phone made for the app (an Android phone sends none). No licence number is ever readable in a club check-in. Your licence number and weapon ID stay on your phone — only a one-way code derived from each of them travels, and neither the club nor anyone else can read the numbers back out of it. (The numbers themselves do sit in a backup file you make of your own data — see Cloud backups above. That is your copy, not a club's.) None of it is sent to us, and we never receive any of it — the transfer happens phone-to-phone, inside the code itself, and works with no internet connection at all. A club's record of who attended, and which weapons they said they used, lives on that club's device, and the club can export it.

The identifier shared there is the App Attest key identifier described under Random device identifier, not the random device identifier we key your data by. It tells nobody who you are — but a club that has scanned your code holds your name and that identifier side by side, which we never do.

A club can also check you in by typing your code, if its device has scanned your code before. Then only your name and code are recorded, with no weapons.

If you ask a club to check a score, the app shows a second code that carries your check-in code and name, the target, the name of the gun, when the series was shot, the score and the position of every shot — no photo. The person running the club's pass looks at your paper target and enters the pass code, and the club's device then records what that code held, together with the name of whoever started the pass. This also happens phone-to-phone with no internet, none of it reaches us, and your own phone is not told the result.

How long a club keeps its register is for the club: it stays on the club's device until that device's app data is removed, and the app does not delete the register on a schedule. Because it holds members' names, the club's device is locked behind the phone's own Face ID, fingerprint or passcode where one is set up.


Third parties at a glance

A complete list of services that may receive data when you use the app, in alphabetical order. This table is the current, authoritative list of who our AI vision provider is — we may switch providers as the product evolves, and rather than naming one throughout this policy, every other section just points back here:

ServiceWhat they receivePurposeRegion
Apple App AttestDevice attestation tokenAnti-fraud, authenticationApple-controlled
Apple DeviceCheckDevice token + one flag: free scans used (iPhone only)Free-scan quota anti-fraudApple-controlled
Apple (App Store lookup)Your phone's country code + app id (iPhone only)Check whether a newer version is outApple-controlled
CloudflareAccount identifier + usage events (analytics transport)Analytics traffic routing (PostHog managed reverse proxy)Global edge (dynamically assigned)
Expo (EAS Update)EAS-Client-ID + app version, build and platformOver-the-air JavaScript updates (checked on every launch)United States
Google (Gemini)Target photos you submit for AI scoringAI shot-hole detectionUnited States
Google Play IntegrityDevice integrity tokenAnti-fraud, authenticationGoogle-controlled
PostHogAccount identifier (users.id) + usage eventsProduct analyticsEU (eu.i.posthog.com)
RevenueCatPurchase identifier + purchase tokensSubscription management (configured on every launch)United States
SentryAccount identifier (users.id) + crash reportsBug fixingEU/US (SCCs)
Vercel (AI Gateway)Target photos you submit for AI scoringRouting to the AI modelUnited States

The AI vision provider named above and the Vercel AI Gateway only receive a photo when you explicitly accept AI scoring for that target. We send only the image needed to score that target — your random device identifier and other personal data stay on our own servers and are not forwarded to the AI provider.

We do not use any other third-party SDKs or services that receive user data.


Legal bases (GDPR)

Where the GDPR applies, we rely on the following legal bases:

  • Legitimate interest (art. 6(1)(f)): crash reports and diagnostics (keeping the app and the website working), product analytics (improving the product — with the in-app de-identification switch in Profile → Privacy & terms), the website's cookieless visit and page-speed statistics (Vercel Web Analytics and Speed Insights), import mapping votes, detector measurements, the device attestation and Apple DeviceCheck flag used for anti-fraud and quota enforcement, and the minimal anti-fraud record we keep after a deletion request (see Data retention). You have the right to object at any time (art. 21) — use the in-app switch where one exists, or contact us.
  • Consent (art. 6(1)(a)): photo upload for AI scoring and detector training — one strictly opt-in permission (the Share target photos toggle) that you can withdraw at any time in Profile → Privacy & terms.
  • Contract (art. 6(1)(b)): purchase verification and subscription management.

Data retention

  • Random device identifier: kept as long as your device is paired with our service. You can request deletion of the data linked to it at any time (see Your rights).
  • Anti-fraud anchor: after a deletion request we keep a minimal record — your device and purchase identifiers and the AI-credit ledger — for as long as needed to prevent purchase replay (for example, deleting and re-pairing to restore spent credits). Legal basis: legitimate interest (GDPR art. 6(1)(f)); you may object under art. 21 by contacting us.
  • Crash reports: retained by Sentry for 90 days by default, then automatically purged.
  • Product analytics events: retained by PostHog for the duration of our analytics plan, then purged.
  • Import mapping votes: kept for as long as we find the tallies useful. A vote sent with Link usage data on carries your account identifier, and Delete my data does not remove or unlink it (it only clears votes still waiting on your phone); a vote sent with it off carries none.
  • Apple DeviceCheck flag (iPhone): held by Apple, not by us, and not removed by a deletion request — Delete my data does not reset it, and neither does reinstalling the app. That is deliberate: it is what stops the free scans being renewed by a reinstall.
  • Detector measurements: kept for as long as we decide offline scanning from them. A deletion request unlinks them from your device identifier straight away (see Your rights).
  • Shared target photos: retained for as long as we operate the detection-training program. We may delete photos at any time once we no longer need them, and you can ask us to unlink photos from your device identifier (see Your rights).
  • AI scoring data: photos you submit for AI scoring are retained the same way as shared target photos (above). The small technical request records (model, token counts, cost, timing) are kept for billing and abuse-prevention and are not used to identify you. Their deletion is manual — no job expires them on a schedule — so we keep them until we no longer need them and remove them by hand. A deletion request unlinks them from your device identifier straight away (see Your rights).
  • Purchase records: retained as required by Apple's, Google's, and our tax/accounting obligations. For AI credits, we additionally retain the RevenueCat transaction id backing each purchase in our append-only ledger, for as long as needed to verify that purchase — no card data is included, since we never receive it (see the RevenueCat section above).

Your rights

We do not collect names, and the only email address we might hold is one you typed into a feedback report yourself — so in most cases we cannot identify you from a personal name. We can identify data linked to your random device identifier. Tap the Support ID row under Profile in the app to copy what we need. The row itself shows your purchase identifier (the id RevenueCat knows your purchases by); the copied text adds a Device ID line holding the account identifier our server knows your device by (the users row id described above), once the app has contacted our server. The purchase identifier finds a purchase; the Device ID finds the data linked to your device.

You can ask us to:

  • Provide a copy of any data linked to your device identifier
  • Delete the data linked to your device identifier, except a minimal anti-fraud record (your device and purchase identifiers and the credit ledger), purchase records we must keep for accounting, and any import mapping votes sent with Link usage data on (see Data retention). Photos and AI records are unlinked from your identifier rather than deleted from the training corpus.

Easiest way to delete: open the app and tap Profile → Data & transfer → Delete my data. The action is irreversible — it unlinks your uploaded photos and AI records from your device identifier and turns sharing off. Your local sessions and matches stay on the device; uninstalling the app removes those.

What happens after you delete: deletion does not happen automatically again on the next launch, and nothing is silently re-created either. The app only contacts our servers again when you use a feature that needs them (AI scoring, photo sharing, purchases, pairing), and doing so re-creates the link to the same anti-fraud record — so a repeat purchase is recognised as belonging to the same customer, but nothing you had unlinked is re-attached.

If you'd rather email, copy your Support ID (the Support ID row under Profile — tap to copy) and send it to shooter.support@gmail.com.

You can also exercise the following rights unilaterally, without contacting us:

  • De-identify product analytics: turn off Link usage data in Profile → Privacy & terms — events continue anonymously (no device identifier, no profile, a fresh random identifier every launch) instead of stopping, and crash reports also arrive without your device identifier
  • Stop future photo uploads: turn off Share target photos in Profile → Privacy & terms
  • Stop all telemetry: uninstall the app
  • Delete local data: clear the app's storage or uninstall

If you are in the EU, UK, or another jurisdiction that grants you data-protection rights (GDPR, UK GDPR, CCPA, etc.), you have additional rights to access, rectify, restrict, port, and object to the processing of your data. Contact us at shooter.support@gmail.com to exercise them.


International transfers

Most data is processed in the EU (PostHog's storage, our own infrastructure). Analytics events transit Cloudflare's global edge on their way to PostHog, and Cloudflare may process that traffic from multiple or dynamically-assigned locations that can be outside the EU before it reaches PostHog's EU servers. RevenueCat is operated from the United States, Sentry may process data in the US as well as the EU, and Expo — which serves the app's over-the-air JavaScript updates and therefore sees an update check from every launch — is operated from the United States. If you opt in to AI scoring, the target photo is processed in the United States by our AI vision provider (named in the Third parties at a glance table) via the Vercel AI Gateway. By using the app you consent to your account identifier, usage events, crash reports, purchase identifier and any purchase tokens being transferred to Cloudflare's global edge (as part of routing analytics traffic to PostHog), and to Sentry's and RevenueCat's US infrastructure, and to your update-client identifier and app version reaching Expo's US infrastructure on each launch, where applicable, and — only when you accept AI scoring — to the relevant target photo being transferred to our AI vision provider and Vercel in the United States, in each case under standard contractual clauses.


Children's privacy

Shooter is not directed at children under 13 and is intended for users old enough to legally handle firearms in their jurisdiction. We do not knowingly collect data from children. If you believe a child has used the app, contact us and we will delete the data linked to that device — photos and AI records are unlinked from it, and sharing is turned off. As with any deletion request, the minimal anti-fraud record described under Data retention above survives: the device and purchase identifiers themselves are kept, because they are what stops a deletion being used to reset a purchase limit. We will not delete that record, and we would rather say so here than promise an erasure the system does not perform.


Changes to this policy

If we make material changes, we will update the Last updated date at the top of this page and surface a notice in the app on next launch. Continued use of the app after a change constitutes acceptance of the updated policy.


Contact

Privacy questions, data-deletion requests, or anything else:

shooter.support@gmail.com