900words privacy policy

Last updated 2026-10-04

900words is a vocabulary game for learning Danish or German. There is no account, no sign-up and no way for the app to know who you are. This page says exactly what leaves your device and why, and it is short because very little does.

Your progress stays on your device

Every word you learn, every round you play, and every setting lives in the app's local storage on your phone. Your collection and journey are never uploaded as a cloud save. The backup button in Settings writes a file wherever you choose; the app never sees it again unless you restore it. Deleting the app (or clearing the site's data) deletes that local progress.

What is sent when Casey plays

Casey, the AI companion, is played by a language model. To produce a clue, a guess or a translation, the app sends the words on the current board, the clues and guesses exchanged this round, and whatever you type into the clue and look-up fields to our server (a Cloudflare Worker). The server constructs Casey's instructions, asks an AI model provider, checks the answer and returns only Casey's finished decision to the app. Casey sees her own target words when giving a clue, but neither the server nor the model is sent the player's secret key.

These requests carry no name, account, contact details, API credential or chosen model. There are none to carry. We do not store request content. The model provider processes the server's prompt to produce the answer under its own terms. Casey's authored clue books and evaluator data stay on the server and are not downloaded by the app.

Offline Casey (optional)

In the iPhone app you can download offline Casey in Settings. The app then downloads Google's Gemma model file once from Hugging Face (huggingface.co), which sees an ordinary download request, such as your IP address, under its own terms. When offline Casey plays, her clues and guesses are worked out on your phone and are not sent anywhere. Looking up a word that the app's own dictionary does not contain still asks our server when you are online. You can remove the model in Settings at any time.

How the next board is checked

After a round in the first, second or last city of the journey (Sønderborg, Ribe or København in Danish; Flensburg, Lübeck or Berlin in German), the app prepares possible next boards and asks the same first-party Cloudflare Worker which ones meet the game's connection floor. This is necessary gameplay processing and happens even under Private play. The request contains only candidate word IDs, up to four recent board ID sets, and anonymous per-word practice-need weights. It contains no secret keys, clues, identity or installation ID, raw learning history, or analytics.

The Worker uses those values only in memory to check the batch and returns only opaque candidate positions. It does not log, store, join, analyse, retain or use this request for training, and it does not send it to an AI model provider. If the check is unavailable, the app uses its ordinary local board draw and does not claim that board passed the server check.

One random number, for rate limiting

To keep Casey's server affordable, the app generates a random installation ID on your device and sends it with each AI request. Our server counts requests per ID per day and refuses further ones past a daily cap. The ID is random, is generated and stored only on your device, means nothing anywhere else, and identifies an installation, not a person. The daily counts expire on their own.

Purchases

Two games a day are free. Unlimited play is a purchase in the app, either a monthly subscription or a one-time purchase. On iPhone, Apple handles all of it through your Apple Account. On Android, Google Play handles all of it through your Google Account. The app only asks the store, on your phone, whether a valid purchase exists. On Android it checks the store's signed answer on the phone itself. We never receive your payment details, your store account or your purchase history, and nothing about purchases is sent to our server. Apple's or Google's own privacy policy covers the payment.

Google Play review access (Android)

The Android app has a short last section in Settings where a Google Play reviewer can enter a review code, so they can check unlimited play without paying. Only someone who has the code can use it. Entering a code sends that code to our server, which answers yes or no; the code itself is never logged or stored. To stop people guessing codes, the server counts attempts per network address per day. That count is kept under the address for two days and then deleted, and nothing else about the request is stored. A code that is accepted is remembered only on the phone, for 30 days. It is never part of a backup file and is not a purchase.

Your optional data-sharing choice

After the first wrap-up that packs at least one word, 900words asks once how you want to share play data. Nothing is preselected. An unmade choice and Private play send no optional game event. The choice never changes access to the game and remains editable in Settings. It controls only the optional events below, not the transient gameplay processing described above.

Anonymous diagnostics sends round-level facts: a random event ID and time; language and city; normal or wrap-up mode; won or lost and the engine's outcome reason; and counts for board size, turns, look-ups, packed and wrapped words, and newly collected or discovered words. It does not send word IDs, clues, guesses, look-up text, secret key roles or contact details. These events expire after 30 days.

Diagnostics plus Casey-learning examples sends those same facts and also the clue giver, clue text and number, guessed word IDs, and each guess's green or bystander outcome. This can include language you typed. It is used to improve Casey's clues and guesses; it is not silently passed on as general model-training data. These examples expire after 90 days.

Optional events go only to the same owner-operated Cloudflare Worker that serves Casey. They are stored in a separate database under the random installation ID so this phone can delete them. Choosing Private play stops new events immediately and requests deletion; Settings also has a separate Delete shared data button. If you delete the app before using that button, the random ID is lost and the remaining records disappear at their 30- or 90-day automatic expiry.

Anonymous usage statistics

The app counts a few things so we can see whether it works: that it was opened, how far the introduction got, that a round started and how it ended (which city, which mode, won or lost, how many clues), that a recording or Casey failed and of what kind, and how a question in the app was answered. These counts are sent to our own server (the same Cloudflare Worker) when the app goes to the background, and are stored as totals per day, app build, platform and language. They carry no identifier of any kind: not the random rate-limiting number above, not a device or advertising identifier, and no words, clues or free text. So they cannot be linked to you or your phone, and the server refuses a batch that carries one. No third-party analytics service is involved. You can switch this off in Settings under Data.

What is not involved at all

No advertising, no tracking, no third-party analytics SDKs, no cookies beyond the local storage described above. Optional first-party diagnostics run only after the explicit choice above. Word audio is ordinary static files the app downloads and caches; the app has no microphone access and records nothing.

Changes and contact

Questions and concerns can be sent to [email protected], or through the support contact on the App Store or Google Play listing. This policy is bundled with the app; the stores' Privacy Policy links point to the same text.