What data each part of Medjed touches, which permissions it asks for, where the data is stored and for how long: it's all on this page.
In short
Medjed isn't listed on any app store, so there's no store review checking it for you. That's why we've written down, in one place, what data each part of Medjed touches, which permissions it asks for, where the data is stored and for how long.
Medjed is made by an individual developer in Taiwan. This page was written by checking each item against the code as of 2026-10-13. It isn't marketing copy: where something can't be done or hasn't been fixed yet, we say so plainly.
What the server stores is only for licensing. This table lists what relates to you personally, split into the desktop app and the phone apps; the full list is in sections 3 and 4.
| Category | Stored on the server: desktop app | Stored on the server: phone apps | Not stored on the server |
|---|---|---|---|
| Contact details | Email: only if you subscribe or sign in with email (the same on the desktop app and phones). If you only request a verification code, it's deleted within 1 hour. | Name, phone number, address, date of birth, biometric data (if Polar provides your name, it's only used to greet you in the license email). | |
| License and subscription | License keys are stored only as hashes (only the desktop app takes a license key); if you subscribe, also Polar's subscription ID and customer ID. | The license key itself, your card number (payment is completed at Polar). | |
| Device | Machine ID: an 8-character hash computed from "PC name + Windows user name". Hardware ID: a hash of Windows' MachineGuid, computed on your PC before it's sent. App version. | A random device ID generated by the app and the device public key; the phone's name, model, OS version and app version. On Android the name is "brand + model"; on iPhone it's the generic name "iPhone" plus the model identifier (for example iPhone14,2). If you start a trial on the phone itself, also a hash of the system ID / trial identifier. | Your PC name, your Windows user name and the MachineGuid itself (the desktop app only sends hashes); the name you gave your phone; your advertising ID. |
| Usage records | Trial start time and the last time you opened the app. After you activate a license key or sign in with email, also the activation / unbinding / connection log (connections at most once every 6 hours; only the latest 200 entries). | Date added and last online time. | Per-person feature-usage analytics (who tapped what, how long they used it; the warehouse only keeps daily totals, see section 4) and cross-app tracking data. |
| Network | Hashes of your IP address and of the network you connect from, computed with a server secret key (for rate limiting and preventing repeated trials; for how long they're kept, see section 4). | Your IP address itself (for the host's access logs, see section 4). | |
| Location | — | Your location, favorites, routes and movement history (for what map services see, see section 7). | |
| Other | — | Contacts, photos, other apps' data. | |
The server is an API on Vercel plus an Upstash database. The data in the database that relates to you falls into the categories below. For a summary of how long each is kept, see section 4.
| Data | What it is | Kept for |
|---|---|---|
| PC machine ID | An 8-character hash computed from "PC name + Windows user name". The server receives the hash, not the names themselves. | In trial records: 400 days after last use. In license bindings and logs: until you ask us to delete it. When the PC pushes a trial to a phone, that phone's device record also uses the machine ID as its key: kept until that phone signs out or you ask us to delete it. |
| Hardware ID | Windows' MachineGuid, hashed on your PC before it's sent. It stops people from renaming their PC to get another trial. | 400 days after last use |
| Trial record | Trial start time, the last time you opened the app, app version. | 400 days after last use |
| Data | What it is | Kept for |
|---|---|---|
| License key | Only a hash is stored, never the key itself. | Until you ask us to delete it |
| Binding status | Which PC it's bound to (machine ID), expiry date, last connection time, number of PC switches. | Until you ask us to delete it |
| Activation / unbinding / connection log | Each entry has a time, the machine ID and a short note (for example the app version). For a license issued automatically by a subscription, the first entry includes the Polar subscription ID and email. Connections are logged at most once every 6 hours. | Only the latest 200 entries; kept until you ask us to delete it |
| Licenses used on each PC | Records, by machine ID, the hashes of the licenses used on that PC, so we can look them up if you forget your license key. | Up to 50 entries; kept until you ask us to delete it |
| Subscription data (from Polar notifications) | Email, Polar subscription ID and customer ID, subscription status (active / paused / ended), next renewal date, and whether it has been canceled. If Polar provides your name, it's only used to greet you in the license email and isn't stored separately. | Until you ask us to delete it |
| Refund record | When Polar notifies us of a refund, the time is recorded on the license, and the log contains the Polar order ID and amount. | Until you ask us to delete it |
| Support record | When an admin disables a license by hand, the reason, a short note and the time are recorded. | Until you ask us to delete it |
| Pending subscription status | If Polar's pause or end notification arrives before the license exists, that status is held temporarily under the subscription ID. | 30 days |
| Data | What it is | Kept for |
|---|---|---|
| Device data | A random device ID generated by the app, the device public key (the private key stays on the phone), device name, model, OS version, app version, date added and last online time. On Android the device name is "brand + model"; on iPhone it's the generic name "iPhone" that the system gives the app, plus the model identifier, not the name you gave your phone (from iOS 16 on, the system doesn't give apps that name). | Until you ask us to delete it (trial phones too) |
| Trial started on the phone | Android sends the system ID (ANDROID_ID); iPhone sends a trial identifier generated by the app and stored in the Keychain. The server only stores their hashes, to make sure each phone can use the trial only once. | Trial record: 400 days after last use. The trial phone's device record also uses this hash as its key, and is kept until this phone signs out or you ask us to delete it |
| Records for the phone-switch limit | For each platform, the time of the last device switch, plus the previous device's ID and key fingerprint. The "one switch every 7 days" rule relies on these. | Until you ask us to delete it |
| Data | Kept for |
|---|---|
| License, email, phone device records (including trial phones), refund and support records, licenses used on each PC | Not deleted automatically for now; kept until you ask us to delete it. |
| Trial records (machine ID, trial start time, hashes of the hardware ID / phone identifiers, network hashes) | Kept for 400 days after last use. If you ask us to delete your data, this part stays until that period ends, to prevent repeated trials. Exception: a trial phone's device record also uses the hash of the phone identifier (or the machine ID, for trials pushed from the PC to a phone) as its key; that record is kept until the phone signs out or you ask us to delete it. |
| Verification codes | 10 minutes |
| Verification code request count | 1 hour |
| IP hashes (for rate limiting) | 10 minutes to 2 days |
| Network hashes | PC trials: with the trial record, at most 400 days after last use. Trials pushed from the PC to a phone: 1 day after the trial ends. |
| Warehouse claims | About 2 days |
| Warehouse daily usage totals (no individual accounts) | 90 days |
| Pending subscription status | 30 days |
| Old-format records from before the Oct 11 update | No longer used from the moment this update goes live, and all of them are deleted immediately afterwards (see Old-format records above). |
| Item | How it flows |
|---|---|
| Desktop installer | The download button on the website redirects to the official release on GitHub. |
| Desktop updates | When the app starts and every 6 hours after that, it reads a version file from GitHub to compare. If there's a new version it only lets you know; it downloads only when you click. |
| Android app | Usually installed for you by the desktop app. After that, the app reads companion.json from the website at most once every 6 hours. When there's a new version, it downloads it from GitHub only after you confirm, then hands it to the system to install. |
| iPhone app | The IPA is hosted on the website and installed with SideStore (the desktop wizard can put it on your phone for you). The app reads sidestore.json from the website at most once every 6 hours to check for a new version. |
These version checks only download files and don't send any of your data, but whoever serves the download sees your IP address.
| When | What's sent |
|---|---|
| Trial start (desktop app) | Every time the app opens, it sends "machine ID, app version, hardware ID hash", and the server replies with the date your trial started. |
| Email sign-in: sending your email | Your email. The server only sends a verification code if that email has an active subscription; the response is the same whether or not a code was sent. |
| Email sign-in: entering the code | The desktop app also sends the machine ID and app version; phones send the device data and device public key listed in section 3. |
| License activation | License key, machine ID, app version. The server only stores a hash of the license key. |
| Periodic license check (desktop app) | When the app opens, every 6 hours, and also when you switch back to its window (at most once every 10 minutes). It contains only the machine ID and a sign-in credential (token). |
| Periodic license check (phones) | About every 10 minutes while the app is open or simulating. It contains only the token, a timestamp, a device signature and the app version. |
| How you use it | How it flows |
|---|---|
| PC → Android | Sent with adb over USB to Medjed on the phone. Wi-Fi adb you've set up yourself, or an emulator on your PC, goes the same way. |
| PC → iPhone | Handed to the "iOS service" on your PC (it only accepts commands locally, on 127.0.0.1), then sent to your own iPhone over USB or your home network. |
| Android phone on its own | The mock location is set inside the phone. |
| iPhone on its own | Medjed connects through LocalDevVPN to the phone's own developer services (10.7.0.1). |
The PC and the phone relay through adb. The small servers on both the phone and the PC only accept connections from the same device, and require authentication.
A fixed list written into the server code; the app just downloads it (the full list is for subscribers). Again, only the token is sent.
Maps and place names come from third-party map services. Your PC or phone connects to these services directly; the requests don't go through our server.
| Purpose | Desktop app | Phone apps (Android, iPhone) |
|---|---|---|
| Map tiles | tile.openstreetmap.org or OpenFreeMap (depending on the map style you choose) | OpenFreeMap |
| Place search | Nominatim, falling back to Photon if that fails | Nominatim |
| Place name lookup (reverse geocoding) | Not used | When the map stops moving, asks Nominatim for the place name at the map center |
| Version | Coordinates sent |
|---|---|
| From the next version after Android 1.0.4 / iPhone build 35 | First rounded to 3 decimal places, about 100 m |
| Android 1.0.4 (the current release) and earlier, and iPhone build 35 and earlier | Full coordinates |
Please update once the new version is out.
The following providers receive what they need to provide their service.
| Service | Used for | What it receives |
|---|---|---|
| Polar | Payments (Merchant of Record) | Your payment details at checkout stay with Polar; we never see your card number. Polar notifies us of the subscription's email, subscription and customer IDs, status and renewal date; for a refund, it also notifies us of the order ID and amount. Our server sometimes checks a subscription's status with Polar using the subscription ID. |
| Resend | Sending email | Your email address and the message content, that is, the verification code email or the license email. |
| Vercel | Hosting the website and the API | Every request to the website and the API. It keeps its own access logs (IP address, path). |
| Upstash | Database | Stores the data listed in sections 3 and 4. |
| GitHub | The desktop installer, Android update files and desktop update checks; some fonts in the iPhone app are also downloaded from GitHub | Your IP address. |
| Map services (OpenStreetMap, Nominatim, OpenFreeMap, Photon) | Map tiles, place search and place name lookup | See section 7. |
| Google Fonts | Fonts for the website and the desktop app. The Android app's fonts are downloaded by Google Play services on the phone | Your IP address, but not your location. |
| unpkg.com | The desktop app still contains an old "phone browser remote control page". Since October it only runs locally on your PC, and there's no way to reach it from the interface | The map library is loaded from unpkg only if you open that page in a browser yourself. Normal use never connects to unpkg. |
| iloader, SideStore, LocalDevVPN | Third-party tools for installing on iPhone; not our services | For how they handle data, refer to their own documentation. |
| What it reads or sets | Details |
|---|---|
| Windows' list of USB devices | Recognizes your phone's brand so it can show you the matching guide. |
| MachineGuid in the registry | Used to compute the hardware ID hash (see section 3). |
| Where the emulator is installed | Finds the Android emulator on your PC and connects to it with adb (see section 6). |
| adb: app status and phone info | Checks the status of Medjed's own app, plus the phone's brand and OS version. |
adb: the phone's system ID (ANDROID_ID) | Used only on the PC to merge duplicate connections to the same phone (for example when it's connected over USB and Wi-Fi at the same time). Never uploaded. |
| adb: one-click mock location setup | Sets Medjed as the mock location app and turns off the mock location permission for other apps (see section 2). |
| adb: when reinstalling Medjed | Grants its location and notification permissions directly, and selects it again as the mock location app (see section 10). |
Listens only on 127.0.0.1, to sync favorites with an Android phone connected over USB. Other devices on your local network can't connect to it.
Many apps ask for a long list of permissions as soon as they're installed. Below are all the permissions the Medjed Android app declares, and whether you'll be asked for each. The "setup checklist" means the "Before you start" (開始前的準備) screen in the app.
Asks youYou turn it on in SettingsAsked only if you use the featureAutomatic, no prompt
| Permission | Will you be asked? | Why it's needed | Limits and notes |
|---|---|---|---|
| Location (precise / approximate) | Asks youThe first time you open the map, or at step 1 of the setup checklist. | Lets the map show where you are now. Android also requires this permission for the "location" foreground service that keeps running while simulating. | It doesn't ask for the background location permission (on Android 10 and later, the most you can grant is "While using the app"; Android 8–9 doesn't separate foreground and background location, and the app only reads your real location while its screen is open). Your real location is never uploaded to our server; but map services receive tile requests for that area, see section 7. |
| Notifications | Asks youOn Android 13 and later, at step 4 of the setup checklist. On Android 12 and earlier the system allows it by default and doesn't ask. | Shows "Medjed simulating" (Medjed 模擬中) and a stop button, a reminder when a new version has finished downloading, and an alert when your license is no longer valid and simulation has been stopped. | From the next version after 1.0.4, the notification no longer contains coordinates, and they can't be seen on the lock screen either. |
| Unrestricted background use (recommended) | Asks youWhen you tap "Set up" (設定) at step 6 of the setup checklist. | So the system doesn't stop the simulation and the joystick after you swipe the app away. | — |
| Mock location app (Developer options › Select mock location app) | You turn it on in SettingsChoose it in Developer options, or use the desktop app's one-click setup. When the app is reinstalled, the desktop app also selects it again automatically (see USB debugging below). | This is Android's official mechanism for changing location. Without selecting it, the location can't be changed. | The one-click setup selects Medjed for you and turns off the mock location permission for other apps, the same as choosing Medjed yourself in Developer options. |
| Display over other apps (optional) | You turn it on in SettingsAt step 5 of the setup checklist, or when you open the floating joystick (懸浮搖桿) without having allowed it yet, the app takes you to the settings page; on Xiaomi phones, the first time you open the joystick it also takes you to turn on background pop-up windows. | Needed for the floating joystick. | Only used to show the joystick; it can't see other apps' screens (see "Permissions we don't ask for" below). |
| Install unknown apps | You turn it on in SettingsOnly for in-app updates: when a downloaded new version is about to be installed (after you tap "Update" (更新) and the download finishes, or when you tap "Install" (安裝)), the app takes you to the settings page. | Needed for in-app updates. | It only installs our update files, and the system refuses to install a file with a different signature. |
| Health Connect steps (read + write, optional) | Asked only if you use the featureOnly when you tap "Grant Health Connect access" (授權 Health Connect) on the Steps (步數) page. | Reads today's steps and writes the steps you choose to add. | The data stays in Health Connect on your phone. |
| Internet | Automatic, no promptGranted at install (Android doesn't ask for this kind of permission). | Connects to our license server, map services and update checks, plus the small local server used to sync with your PC. | — |
| Network state | Automatic, no promptGranted at install. | Used by the map component to tell whether you're online. | — |
| Wi-Fi state | Automatic, no promptGranted at install. | Not used by the app at the moment (a declaration left over from an early version). | It doesn't read your Wi-Fi network name or nearby networks. |
| Foreground service (location type) | Automatic, no promptGranted at install. | The service that keeps running while simulating. | — |
| USB debugging (in the phone's Developer options; not an app permission) | You turn it on in SettingsThe first time you connect to a PC, the phone asks whether to allow that PC. | Lets the desktop app install the app, set up mock location in one click, send locations and push favorites. | While it's on, any PC you've tapped "Allow" for can control this phone, so you can turn it off when you're not using the PC. When reinstalling the app, the desktop app grants location and notification permissions directly with adb and selects Medjed again as the mock location app, without showing a prompt and without first checking whether you had allowed them before; if you don't want that, you can turn them off in system settings. |
There's also one internal permission added automatically by Android's development libraries (DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION). It's only used to stop other apps from sending messages into Medjed.
It doesn't use screen recording either, so it can't see other apps' screens.
Below are all the permissions the iPhone app declares, plus the settings you need to change yourself. Permission prompts are shown by iOS; you can decline, and change your choice later in Settings › Medjed.
Asks youNo promptYou turn it on yourselfNot a system permission
| Item | Will you be asked? | Why it's needed | Limits and notes |
|---|---|---|---|
| Location (While Using the App) | Asks youThe first time you open the map, connect or pair. | Shows your location on the map, and keeps the connection alive when the screen is locked or you switch to another app. | It doesn't ask for "Always". Your location is never uploaded to our server; for what map services see, see section 7. |
| Local network | Asks youThe first time you connect or pair. | Connects to the phone's own debugging services; while pairing, it advertises itself on the local network. | It doesn't scan other devices on your home network. |
| Notifications | Asks youThe first time it connects (tapping "Connect" (連線), or automatically when you send a location from the map) or pairs ("Pair this phone" (配對這支手機)). | Disconnection alerts, the pairing code, and reminders when the app's signature is about to expire. | All of them are local notifications sent by the phone itself, not through a push server. If you don't allow them, a disconnection is only shown inside the app. |
| Background audio | No promptA background mode the app declares. | Plays near-inaudible silent audio so the app isn't suspended in the background. | It mixes with your music instead of interrupting it, and doesn't use the microphone. |
| Background location | No promptA background mode the app declares; you need to allow location (above) first. | Keeps the connection alive when the screen is locked or you switch to another app. | Uses the lowest accuracy (about 3 km); the location it receives isn't used for anything and isn't uploaded. While background location is in use, a blue location indicator may appear in the status bar. |
| Developer Mode | You turn it on yourselfIn the iPhone's Settings app. | An official Apple setting; iOS needs it to change location. The desktop wizard makes this option appear, and you turn it on yourself. | While it's on, Apple disables some additional protections, and other apps can more easily read debug information. We recommend keeping it on only while you use Medjed. When you don't need it, you can turn it off in Settings › Privacy & Security › Developer Mode, and turn it back on when you do. |
| Pairing file | Not a system permissionGenerated by the desktop wizard and placed on the phone. | The "key" that lets Medjed on your phone control location without a PC. It's generated by the PC and placed in Medjed's Documents folder (visible in the Files app). | Two copies are also kept on the PC: one in Medjed's folder (see section 12), and pymobiledevice3, the open-source tool used for pairing, also stores a pairing key in %USERPROFILE%\.pymobiledevice3. Please don't send them to anyone or post them in public channels. |
| LocalDevVPN | Not a system permissionA separate app that you install and turn on yourself. | A VPN app on the phone. Medjed only uses it to connect to the phone's own developer services (10.7.0.1). SideStore also relies on it for installing and refreshing apps. | For how LocalDevVPN handles data, refer to its own documentation. |
| SideStore | Not a system permissionA separate app that you install yourself. | Installs Medjed with your own Apple ID. | Apps installed with a free Apple ID need to be refreshed in SideStore every 7 days. |
Background audio and background location are on by default. You can turn them off with the gear icon on the app's Settings › Connection & pairing (設定 › 連線與配對) page; with them off, the connection may drop when the screen is locked or you switch to another app.
| Data | Where it's stored |
|---|---|
| Main data | Favorites, routes, categories, and the "Send / movement log" (the latest 200 entries, including coordinates you've sent) are stored in the data folder in the install directory; if the install directory isn't writable, they go to %APPDATA%\Medjed instead. Favorites backed up from the phone before reinstalling the Android app (companion-backups) and the iPhone pairing file (ios-pairing) are also here. |
| Sign-in and trial status | .dat files in %APPDATA%\Medjed, %LOCALAPPDATA%\Medjed and %ProgramData%\Medjed (the sign-in file contains your license key or the email you signed in with), plus the registry key HKCU\Software\Medjed. |
| Automatic backups | %APPDATA%\Medjed\backup, keeping 10 copies, without the movement log. |
| Upgrade backup | %LOCALAPPDATA%\Medjed-upgrade-backup. It stays after you uninstall, so your data can be recovered when you reinstall. |
| iPhone pairing key | %USERPROFILE%\.pymobiledevice3 (see section 11). |
How to delete it:
The installer currently has no code signature, so Windows SmartScreen may show a warning. We plan to apply for code signing, but there's no set date yet.
These are the results when v0.7.0 was uploaded, all with 0 detections. Antivirus databases get updated, so check the links for the latest results.
| File | Scan result |
|---|---|
| Desktop installer (v0.7.0) | View on VirusTotal |
| Android app (1.0.4) | View on VirusTotal |
| iPhone app (build 35) | View on VirusTotal |
You can confirm all of the following on your own phone and PC. If anything doesn't match this page, please let us know as described in section 14.
| What to check | Where to look | What you should see |
|---|---|---|
| Android: the app's permissions | Settings › Apps › Medjed GPS › Permissions (menus differ slightly by brand, for example Xiaomi or Samsung) | Only Location, plus Notifications on Android 13 and later; on Android 14 and later, Health Connect may also appear. This matches section 10. |
| Android: mock location app | Settings › Developer options › Select mock location app | It shows Medjed GPS only if you chose it yourself or set it with the desktop app (the one-click setup, or the automatic reselection when the app is reinstalled; see section 10). |
| iPhone: location | Settings › Privacy & Security › Location Services | Medjed is listed, and its options don't include "Always" (see section 11). |
| iPhone: local network | Settings › Privacy & Security › Local Network | Medjed is listed (this is the "Local network" permission in section 11). |
| iPhone: other privacy items | Photos, Contacts, Camera, Microphone, Health and Tracking on the same screen | Medjed isn't listed in any of them. |
| Windows: running programs | Task Manager (Ctrl+Shift+Esc) › Details |
|
| Windows: network connections | Resource Monitor (search for resmon in the Start menu) › Network, then select the check box next to Medjed GPS.exe | Apart from this PC (127.0.0.1), it only connects to our server (medjed.vercel.app), our website (gps.medjed.app), GitHub, Google Fonts and the map services in section 7 (tile.openstreetmap.org, tiles.openfreemap.org, nominatim.openstreetmap.org, photon.komoot.io). Resource Monitor may show only IP addresses here. python.exe and adb.exe only connect to this PC and your phone. |
| Windows: install location | Open %LOCALAPPDATA%\Programs\Medjed GPS in File Explorer | This is the default install location (you can change it during installation). |
| Windows: uninstalling | Settings › Apps › Installed apps (on Windows 10, "Apps & features") › Medjed GPS | You can uninstall it here. For the folders left behind after uninstalling, see section 12. |
| Installer | Only download from the two places under "Download sources" above. After downloading, run Get-FileHash "file path" in PowerShell (put straight double quotes around the path so it works even if the path has spaces). | This only works for the versions listed above (desktop v0.7.0, Android 1.0.4, iPhone build 35): if the SHA-256 it prints matches the long string in the matching VirusTotal link's address above (upper or lower case doesn't matter), it's the same file. |
Privacy in "Terms & Disclaimer" on our website.
This time we went through the desktop app, Android, iPhone and the server again with one question in mind: can your location leave your device? The conclusion: the server has never had an interface that accepts user locations. But we did find a few things that weren't good enough, and we've fixed them as follows.
Change log