Privacy Policy
This privacy policy describes how the ShotFinder
Android application (the “App”) handles your information.
The App is published by Optygate (“we”, “us”).
The application package name is com.optygate.screenshotsearch.
This version of the policy covers ShotFinder including its online features: Google account sign-in and protected ShotFinder sessions, customization sync, billing and credits, AI Enhance, and opt-in crash reports. Each feature is described below, including exactly what data it sends and where it goes.
Summary
- ShotFinder’s Free tools work on your device. Search, tags, categories, smart actions, and cleanup run on-device and make no network calls.
- Exactly five named surfaces can touch the internet. None runs merely because you open or return to the App. They run only for account and paid-feature actions you choose, a per-screenshot AI Enhance tap, synchronization you explicitly enabled, or opt-in crash reporting.
- Your screenshots and the text extracted from them leave your device only when you tap AI Enhance on a single screenshot. Never automatically, never in bulk.
- Customization sync is off by default, and when on it syncs metadata only (the tags/categories you create or explicitly adopt, manual assignments, suppressions, archive flags, and collections), never your screenshots or their text. Rule- and AI-owned suggestions remain local until you explicitly adopt or edit them.
- The App contains no product-analytics SDK and no advertising SDK. The only telemetry is optional, opt-in crash reporting to our own self-hosted service.
The five network surfaces
ShotFinder reaches the network in exactly five ways. Each is listed in the app under Settings → Privacy → “Network surfaces,” and each is described here.
-
Google sign-in and ShotFinder session: not required for the Free on-device tools, but required
before you buy or restore Pro, use AI Enhance or account-bound credits, or enable
customization sync. Fresh purchases sign in before Google Play Billing; ShotFinder does
not create a signed-out purchase waiting to be claimed later. A legacy or pre-existing
purchase token that has never been attached to a ShotFinder account may still be found by
Restore Purchases after sign-in and attached once to that signed-in account. Sign-in uses
Google services (Android’s Credential Manager and Google identity) to Google-controlled
endpoints; our server verifies the resulting Google ID token. After sign-in, the App
keeps short-lived access and refresh credentials encrypted by Android Keystore keys and
uses a separate non-exportable P-256 key to prove that a renewal comes from that login on
this device. The App renews the 24-hour access token only while performing an online
action you requested or synchronization you already enabled. It does not refresh merely
because the App starts, resumes, or opens Account. Active sessions have a sliding
180-day inactivity limit and can be revoked at any time. Refresh and current-device
revoke go only to ShotFinder’s existing authentication host at
api.shotfinder.optygate.comand contain no screenshot, extracted text, customization, purchase token, or crash payload. Credential Manager is used again only for a required reconnection or the one-time upgrade from the older access-only format. -
Customization sync: off by default after sign-in.
You turn it on yourself in Settings → Account, after a consent screen that names what
crosses the wire. When on, it syncs across your signed-in devices: the custom tags and
categories you created or explicitly adopted, archive flags, collections, suppressed
automatic tags, and category/tag assignments you made by hand. Rule- and AI-owned
suggestions do not sync unless you explicitly adopt or edit them; AI apply, revert, and
content invalidation do not create sync activity.
No screenshots. No OCR text. No app preferences. Talks to ShotFinder’s
own server at
api.shotfinder.optygate.comonly. -
Billing & credits: when you purchase Pro, restore a purchase, top
up AI credits, or when the App verifies your purchase or credit balance before a paid action,
the App talks to Google Play and to our server (
api.shotfinder.optygate.com) to verify the purchase and grant credits. Before each purchase-verification attempt, the App obtains a fresh Play Integrity device attestation bound through one-way hashes to that logical request, your signed-in ShotFinder account, the App package, the product, and a digest of the purchase token. For this check, Google Play Integrity processes the request binding, App package/version/signing certificate, the signed-in Play account’s App-license status, and device-attestation information. The binding contains no screenshot or extracted text. -
AI Enhance: only when you tap the AI Enhance button on a single
screenshot. One tap, one screenshot. Never automatic, never batch. That screenshot and
the text we already extracted from it (the
currentOcrTextfield) are sent to ShotFinder’s API atapi.shotfinder.optygate.com, which forwards them to Google’s Gemini API, the third-party AI provider that powers AI Enhance, on a paid tier whose terms do not use your content to train Google’s models. Your screenshot and its input text are not stored on our server after the call returns. The improved result the AI returns (better text, refined category, tags, entities, and an optional summary) is cached on our server for up to 7 days so that a retry returns the same result without charging you again, then it is deleted. The same user-started request also sends your existing Google Play purchase token to ShotFinder’s API so it can verify the active entitlement and credit operation. Before the upload, the App obtains a fresh request-bound Play Integrity attestation for the same App/license/device anti-abuse check described under Billing. No screenshot bytes or extracted text are included in that attestation. -
Opt-in crash reports: off by default. If you turn
them on, automatic uncaught-crash reports are sent to our own self-hosted
crash-reporting service at
glitchtip.shotfinder.optygate.com. Current-process and historical App-not-responding reporting remain disabled so the App does not need a disk/post-exit path that could upload on a later launch. Each event contains a fresh random per-report event ID and capture time, severity/platform, validated App release/environment, Sentry SDK identity, exception type/module, code-only stack frames limited to class, method, source-code filename, and line, plus device model, OS name/version, and App version. Required delivery framing also contains send time, our public project-routing key, release/environment, SDK name/version plus package/enabled-integration identifiers, and a random SDK-scope trace ID and sampling number. Those scope values may repeat across reports while reporting remains enabled in the same App process; they reset when reporting closes or the process restarts. They and the event ID are not persistent account, installation, or device identifiers. No user, transaction, or replay identifier is attached. Reports have no screenshots, extracted text, file paths, anything you typed, persistent identifier, or breadcrumbs. Native/NDK crash capture is disabled. During an uncaught crash, the App makes one brief in-memory send attempt bounded to 2,000 milliseconds. If it cannot send, the report is not saved or retried. Turning reporting off closes it immediately with a zero-millisecond shutdown wait. Reports are deleted after 30 days.
Adding a sixth network surface would require updating this policy, the in-app “Network surfaces” screen, and the Google Play Data Safety form together.
What information the App accesses
To do its job, indexing and organizing your screenshots, the App needs to read images on your device. Depending on your Android version, this may use one or more of the following permissions:
READ_MEDIA_IMAGES(Android 13 and newer): to read images for indexing.READ_MEDIA_VISUAL_USER_SELECTED(Android 14 and newer): if you grant access only to selected images.READ_EXTERNAL_STORAGE(Android 12 and older): the older equivalent permission.POST_NOTIFICATIONS: to show indexing progress and helpful banners.FOREGROUND_SERVICEandFOREGROUND_SERVICE_DATA_SYNC: so initial indexing can finish reliably.com.android.vending.BILLING: to support in-app purchases through Google Play.INTERNETandACCESS_NETWORK_STATE: for the five network surfaces above. The App does not use the network for indexing, search, tags, categories, smart actions, or cleanup; those run on your device.
Image content is read locally and leaves your device only on a user-initiated AI Enhance tap, as described above.
What the App stores on your device
The App stores the following inside its private application storage:
- References to your screenshot images (as Android MediaStore identifiers, not copies of the images).
- Text extracted from your screenshots by on-device OCR (Google ML Kit Text Recognition, which covers English and 20+ other Latin-script languages).
- Tags, categories, detected entities, and any edits you make.
- Your collections and app preferences.
- If you make a purchase, your Google Play purchase token, so the App can recognize that you have a paid plan.
- If you sign in, your retained account/profile, last-known non-authoritative AI credit display, login-instance/session identifiers, proof counter, and access/refresh credentials encrypted with an Android Keystore AES-GCM key. A non-exportable Android Keystore P-256 key proves session renewal. These credentials and keys are removed on sign-out; the last-known balance cannot be spent offline.
- Local correctness metadata, including a content revision and, for an opaque Photo Picker item, a byte fingerprint and temporary reconciliation proof used to detect changed content or avoid a duplicate card. The raw fingerprint/proof stays on this device and is never synced or exported.
- For an AI Enhance request you start, a small operation journal containing the account and request identifiers, target content revision, low-detail recovery status, last returned balance, and the authoritative credit-restored/no-credit/cancelled-before-charge outcome. This lets the App finish or safely settle the same request after interruption instead of charging twice or guessing.
This on-device data is never transmitted to us or to any third party except through the five network surfaces described above.
What we store on our server
If you sign in and use the online features, our server (at api.shotfinder.optygate.com)
stores only what those features require:
- Account: an internal ShotFinder account UUID, a lowercase SHA-256 hash of your normalized Google Account ID, a SHA-256 hash of your email (for support lookup, never your email in readable form), your display name, and a non-negative session generation used to revoke old ShotFinder sessions after account deletion. The verified raw Google Account ID is transient during sign-in and is hashed before it reaches our database.
- Protected device sessions: for each signed-in device, a pseudonymous session UUID, the internal account UUID, an HMAC-SHA256 of the opaque refresh token (never the raw refresh token), a bounded P-256 public key, the last accepted proof counter, account session generation, and creation/last-refresh/idle-expiry timestamps. These fields are used only for account management, sender-constrained renewal, replay prevention, and revocation. A current-device revoke deletes that live row; an inactive session is rejected at 180 days and deleted by scheduled cleanup; Delete Account removes every live session. An already-created age-encrypted backup may retain an older row only until the backup cleanup deadline described below.
- Customization sync (only if you turn sync on): your custom tags, custom categories, archive flags, collections, suppressions, and User-owned hand edits, plus a one-way composed stable identity for each screenshot (hashed file-name signal, dimensions, and a content digest; never the image itself). The raw Photo Picker fingerprint and reconciliation proof described above are not sent. AI/rule suggestions that you have not adopted are not sent and do not cause that screenshot identity to be seeded. No screenshots. No OCR text.
- Credits & billing: your purchase tokens, plan state, and AI credit balance. Deletion zeros every spendable plan/purchased balance and operational counter and unbinds access. A minimum non-spendable liability record may retain purchased-credit debt and the amount forfeited at deletion so a later Google Play refund or chargeback cannot be erased by deleting and re-creating the account. It can never be used as AI credit. The purchase/original-buyer ledger remains for the narrow restore, fraud, financial, and Play reconciliation purposes described below.
- Play Integrity verification: our API receives the opaque attestation token on a billing or AI request but does not persist or log the raw token or a reusable device identifier. A SHA-256 token hash and the validated request binding/verdict may remain only in a bounded in-memory cache for up to five minutes and never beyond token freshness.
- AI Enhance: a record of each request (account, request id, time, credits used, and success/refund state) kept for accounting and abuse prevention until you delete your account. The input screenshot bytes are never stored; the input text is dropped after the call. The AI’s output is cached for up to 7 days in a separately expired cache that is excluded from backup data, then deleted.
Opt-in crash reports are stored separately on our self-hosted crash-reporting service at
glitchtip.shotfinder.optygate.com, only if you opt in, for 30 days. Its database
is not backed up.
Connection data and operational logs. Any internet connection necessarily
exposes its source IP address to the destination. Nginx’s coarse connection/request
zones are keyed by server name, not client IP, and retain no client key. Our Go API is the
only component that retains the IP, using it as a bounded in-memory abuse/rate-limit key;
idle keys expire within 10 minutes, the map has a 10,000-key hard cap, and the IP is never
written to API or Nginx logs. Both ShotFinder proxies disable access logs and discard
IP/path-bearing error logs. The crash-reporting proxy also clears X-Forwarded-For,
X-Real-IP, and Forwarded before sending a request to GlitchTip. API
request logs contain a standard timestamp, severity, and event name; their request-specific
fields are limited to a standard method class, registered route pattern (or
unmatched), status, response size, duration, and a new server-generated random
request identifier. They do not accept a caller-provided identifier or record the raw request
path/query. Panic recovery records only the standard log envelope, a general recovery event,
and that server identifier—never the panic value, stack, source path, or request target. Other operational errors may
include an internal account/request UUID, product id, and safe state/error category. They never
contain your Google subject or hash, email, auth/session/purchase/Integrity token, screenshot,
OCR text, body, file path, typed content, or a token-bearing provider URL. These container logs
rotate at 10 MiB per file with at most three files, so their retention varies with traffic
rather than following a fixed number of days.
Encrypted backups. We make a nightly backup of the App database, compress and age-encrypt it before upload to a developer-controlled Google Drive remote, and schedule each backup object for deletion once it is 14 days old. The next successful cleanup permanently deletes matching live objects and separately removes trash-only copies left by older cleanup runs. If cleanup is delayed or fails, the object remains encrypted until cleanup succeeds. Google receives ciphertext only; the age private key remains offline. AI result-cache rows and the GlitchTip database are excluded from backups.
On-device OCR
The App reads the text in your screenshots on your device. It uses Google ML Kit Text Recognition, covering English and 20+ other Latin-script languages. It runs entirely on your device and requires no internet connection; the model ships inside the App, so nothing is downloaded from a network at runtime. AI Enhance is a separate, opt-in feature that can send a single screenshot to a cloud AI provider when you tap it (see above).
Google Sign-In and Google user data
Sign-in is never required on first launch or for the Free on-device tools. It is required
before a fresh Pro purchase or restore, before AI Enhance or account-bound credit use, and
before customization sync can be enabled. The App prompts at those entry points rather than
at startup. Sign-in uses Android’s Credential Manager with Google Sign-In, requesting the standard
openid, email, and profile scopes. When you sign in, the
App receives a Google ID token, which our server verifies before issuing a ShotFinder session.
Google user data we access. Through Google Sign-In we access only the basic identity contained in your Google ID token:
- Your Google Account ID: the stable unique identifier (the OpenID
sub) for your Google account. - Your email address, and whether Google has verified it.
- Your name (display name) from your basic Google profile.
How we use this data.
- Google Account ID: identifies your ShotFinder account across sign-ins and across your devices. Our server immediately hashes this case-sensitive identifier with SHA-256 after verification; the one-way hash is what your ShotFinder account, purchase, and optional synced customizations attach to.
- Email address: shown in the App so you can see which account you are signed in as. On our server we keep it only as a SHA-256 hash (for support lookup and account de-duplication); we do not store your email in readable form. The verified flag is used to reject sign-ins from unverified email addresses.
- Name: shown in the App (your signed-in name and avatar initials) and stored on our server as your display name.
Where it is stored and for how long. On your device, your name, email, and
account id remain in the App’s private storage so it can show who is signed in. Access and
refresh credentials are encrypted with authenticated account/session/version binding under
Android Keystore; the renewal signing key is non-exportable. Credentials and keys are
cleared when you sign out. Access-token expiry or temporary offline/server failure does not
clear the profile; definitive revocation, 180-day inactivity expiry, or unavailable/corrupt
Keystore credentials pauses online features until Google reconnection. On our server
(api.shotfinder.optygate.com) we store your ShotFinder account id, your Google
Account ID only as a SHA-256 hash, a SHA-256 hash of your email, and your display name. To
delete your live account data, open Settings → Account → Delete account
in the App. This immediately removes live sync/AI history, zeros all spendable credit and
operational counters, clears display name/email hash, and revokes every existing ShotFinder
session, subject to the narrow non-spendable credit-liability/account/purchase records and
scheduled encrypted-backup cleanup in
“Your control over your data” below. You can also email us at
dev@optygate.com from the address you signed in with; we
complete the same deletion within 30 days.
What we do not access. We request no other Google data. ShotFinder does not access your Google Contacts, Gmail, Drive, Calendar, Google Photos, or any other user Google service, only the basic sign-in identity listed above. The encrypted backup remote described above is the developer’s Google Drive, never your Drive or Drive scope. We do not sell your Google user data, disclose it for another party’s own purposes, or use it for advertising; service processors handle only the limited operations described here.
ShotFinder’s use and transfer of information received from Google APIs adheres to the Google API Services User Data Policy, including the Limited Use requirements. Google’s own handling of your sign-in is governed by Google’s privacy policy. You can sign out at any time from Settings → Account.
Google Play Billing, Play Integrity & credits
In-app purchases are processed by Google Play Billing, a Google service that is part of your device’s Google Play Services. When you make a purchase, your payment interaction is between you and Google; the App receives a purchase token, and our server verifies that token with Google to unlock paid features and grant any bundled AI credits. Google Play Billing does not send us your payment method or billing address. Any display name stored by ShotFinder comes only from the separate Google Sign-In flow described above, not from your purchase. Google’s handling of your purchase is governed by Google’s privacy policy.
Fresh purchases, top-ups, and restores require you to be signed in to ShotFinder before the verification flow. One logical verification keeps the same random request identifier across a short bounded retry sequence, while every network attempt obtains a new Classic Play Integrity token. Its nonce is a SHA-256, domain-separated binding of the request identifier, signed-in server account identifier, App package, product identifier, and a SHA-256 digest of the purchase token. Our server validates that binding before asking Google to verify the purchase; a missing, stale, invalid, or mismatched attestation is rejected. It contains no screenshot bytes or OCR text. The only unbound compatibility case is a legacy or pre-existing token found by Restore Purchases, which may attach once to the account already signed in.
Play Integrity is also used immediately before a user-initiated AI Enhance upload. For every Integrity request, Google says it processes the request hash or nonce; App metadata including package name, version, and signing certificate; the App’s Google Play license status for signed-in accounts on the device; and device information including a key-attestation certificate and device-attestation token. Google states that this data is encrypted, is not transferred to third parties, and is deleted after a fixed retention period. See Google’s Play Integrity data-safety guidance. ShotFinder uses this processing only to verify App, license, request, and device integrity for Billing/credits and AI Enhance; it does not use it to fingerprint or track you. Our server does not persist the raw attestation or a reusable device identifier.
Crash reporting
Crash reporting is off by default. You can turn it on in Settings → Privacy;
the first time you do, the App explains what is collected. When on, automatic reporting covers
uncaught crashes only and sends reports to our own
self-hosted crash-reporting service at glitchtip.shotfinder.optygate.com. Before
sending, the App rebuilds a minimal event containing a fresh random per-report event ID and
capture time, severity/platform, validated App release/environment, Sentry SDK identity,
exception type/module, code-only stack frames limited to class, method, source-code filename,
and line, plus device model, OS name/version, and App version. Sentry's required delivery
framing separately adds send time, our public DSN project-routing key, release/environment, SDK
name/version plus package/enabled-integration identifiers, and a random SDK-scope trace ID and
sampling number. The scope values may repeat across reports while reporting remains enabled in
the same App process; they reset when reporting closes or the process restarts. They and the
event ID are not persistent account, installation, or device identifiers, and no Sentry user,
transaction, or replay identifier is attached. Exceptions, stack traces, frames, and contexts
are rebuilt from strict allowlists; exception messages/mechanisms and every other nested or
free-form event field are dropped. Current-process and historical App-not-responding
reporting are disabled so the App does not need a disk/post-exit path that could upload on a
later launch. Sessions, performance traces, breadcrumbs, root/additional
context, screenshots, view hierarchy, thread dumps, default PII, native/NDK capture, and disk
retry envelopes are disabled. Reports
never contain your screenshots, their text, file paths/URIs, anything you
typed, account id, or a Sentry user/installation identifier. The separate
Play Integrity processing described above is why the App declares “Device or other IDs”
in Google Play Data Safety; crash reports themselves do not carry a persistent device or
installation identifier. If GlitchTip is
unavailable the event is not saved or retried. The uncaught send attempt waits no longer than
2,000 milliseconds; turning reporting off uses a zero-millisecond shutdown wait and deletes
only any legacy crash-envelope cache. GlitchTip deletes events after 30 days
and its database is not backed up. “Anonymous” describes the minimized payload;
the proxy necessarily handles the connection IP transiently but does not log, forward, or
store it.
What the App does not do
- The App does not upload your screenshots or their text to any server except on a screenshot-by-screenshot AI Enhance tap that you initiate.
- The App does not sync your screenshots or the text extracted from them. Sync carries metadata only.
- The App does not include Firebase Analytics, Google Analytics, Mixpanel, Amplitude, PostHog, or any other product-analytics SDK, permanently.
- The App does not include any advertising or ad-attribution SDK.
- The Free on-device tools do not require an account. Pro purchases and restores, AI Enhance and account-bound credits, and customization sync require Google sign-in.
Children’s privacy
The App is not directed to children under 13. We do not knowingly collect any personal information from children.
Your control over your data
You stay in control of your data:
- Revoke the App’s access to your media in Android Settings at any time.
- Pause indexing from Settings. The pause survives restart and stops scheduled, immediate, and media-change indexing until you explicitly resume.
- Reset the local index from Settings → Privacy → “Reset local index”. Reset first stops active indexing, then clears derived OCR/search text, detected entities and actions, AI-applied output, and automatic tag/category choices. It keeps every screenshot card and stable identity, your custom tag/category/collection rows and assignments, manual category/tag edits, archive flags, suppressed automatic tags, collection membership, sync identity/state, entitlement, and any credit-settlement journal needed for an already-started AI request. Ambiguous AI work is routed to safe credit recovery before revisions advance. Retained rows are rebuilt on the next eligible pass, and the indexing schedule is restored without overriding a pause.
- Limited media access and explicit Photo Picker imports are additive. ShotFinder automatically removes an indexed row as missing only after a complete library scan that had Full access both before and after its survivor check; Partial, denied, interrupted, unavailable, or picker-only views do not erase its organization.
- Turn customization sync off or sign out at any time from Settings → Account. Both stop syncing and keep your local customizations. Sign-out attempts to revoke only this device, then removes its local non-exportable keys and encrypted credentials immediately even if offline; other signed-in devices remain active. It also retains that account’s local sync mirror/cursor for safe later reconciliation, but a later sign-in starts with sync off and requires fresh consent.
- Delete your live account data from Settings → Account → Delete account in the App (or by emailing dev@optygate.com from the address you signed in with). This immediately removes synced customizations, AI request/ output history, all spendable AI credits and operational credit counters, display name, and email hash, and revokes every existing ShotFinder session; your on-device index/local customizations and Google Play purchase remain. We retain for the life of the ShotFinder account/billing service only the internal account UUID, one-way Google-subject hash, account/session revision and create/delete timestamps, original-buyer purchase/entitlement/period-grant/Play-notification ledger, and the minimum non-spendable purchased-credit debt/forfeited-value evidence needed to apply a later refund or chargeback correctly. That liability evidence cannot unlock a paid feature or be spent on AI. These records exist solely to revive the same empty account, prevent duplicate grants/fraud, ensure only the original buyer can restore access, and meet financial/Google Play reconciliation needs. They contain no screenshot, OCR, customization, AI output, readable email, display name, or raw Google Account ID. An already-created age-encrypted backup is scheduled for deletion once it is 14 days old. The next successful cleanup permanently removes eligible live and trash-only copies; if cleanup is delayed or fails, they remain encrypted until cleanup succeeds. After confirmed deletion, the App also removes only that account’s local server-identity mirror, parked inbound sync data, consent state, and cursor; another account’s mirror is not removed.
- Turn crash reporting off at any time from Settings → Privacy.
- Clear the App’s storage from Android Settings, or uninstall the App to remove all of its local data.
Data sharing
We do not sell or rent your data. The only third parties involved are Google (for sign-in, Play Billing, Play Integrity abuse-prevention checks) and Google’s Gemini API, which powers AI Enhance, and only for the specific, user-initiated purposes described above. We use Gemini on a paid tier whose terms do not use your content to train Google’s models. A developer-controlled Google Drive remote also stores age-encrypted App-database backups that are scheduled for deletion once 14 days old; the next successful cleanup permanently removes eligible live and trash-only copies, while a delayed cleanup leaves them encrypted until it succeeds. Google receives ciphertext only and the private key stays offline. These providers process data for the described service purpose and do not receive it for advertising or sale.
Security
On-device data lives in the application-private area of your device’s storage, sandboxed by Android from other apps, and protected by your device’s screen lock and disk encryption. Network traffic to our server uses TLS (HTTPS). Server-side data is access-controlled and stored only for the feature/retention periods stated above; backups are encrypted before leaving the server and their decryption key remains offline.
Changes to this policy
If we change this policy (for example, if a future version adds a new feature or changes the AI Enhance provider), we will update this page and clearly mark what changed. The current version of the policy is always available at this URL.
Contact
If you have questions about this policy or about the App, email dev@optygate.com.