Privacy policy
This describes the BikeOtter mobile app and the website at bikeotter.app. It was written by reading what the software actually does — which fields a live-tracking point carries, which sweep deletes it and when, which hosts get contacted — rather than from a template. Where a limit is stated as a number, that number is the one in the code.
Version 1.10 · last updated 9 October 2026 · applies to the app and to this site
The short version
- There is no analytics and no crash reporting. No Google Analytics, no Firebase, no Sentry, no advertising or attribution SDK — neither in the app nor on this website. Nothing here counts you.
- Most of the app needs no account at all. Route planning, route push, ride download, rules and alerts all work signed out, and your settings stay on the phone. An account exists only for live tracking, ride-notification e-mails, the Strava link, route sync if you switch it on (§3.2) and — for Plus riders who switch it on — a backup of their settings (§3.1).
- Your ride files and your voice stay on the phone, and so do your routes unless you switch on route sync. Speech recognition runs on-device; there is deliberately no cloud speech tier. Route sync, and saving a route in the route planner on this website, keep a copy of your routes in your account (§3.2).
- Live tracking is the one feature that publishes your position, to anyone holding the link, for the length of the ride. Heart rate, power and cadence are off by default. Your position points and the session record are deleted together, 7 days after the ride ends or expires.
- Two things the app does without asking: it checks for a code patch on launch, through Shorebird, and that check cannot be turned off. It carries no identity we give it — but it does reach a server. §10.1 explains exactly what we know and what we don't. And on launch it asks RevenueCat, which handles Plus purchases for us, whether you have Plus (§10).
- Nothing is sold, rented or shared for advertising. Ever.
1. Who is responsible
The controller for the processing described here, within the meaning of Art. 4(7) GDPR, is:
OpenBikeControl UG (haftungsbeschränkt)Ulrichstraße 24
71636 Ludwigsburg, Germany
E-mail: support@bikeotter.app
Full company details are on the imprint page. There is no statutory data protection officer; write to the address above for anything on this page.
2. What never leaves your phone
The following is held in the app's own storage on your device and is not uploaded anywhere by BikeOtter. It leaves only if you personally export or share it.
- Your route library, unless you switch on route sync or save routes in the route planner on this website. Routes are files on the phone: geometry plus an index. Sharing a route produces a self-contained link that carries the route inside it; no route is uploaded to a server to be shared.
- Your rides. Rides pulled off the bike computer, and rides recorded by the phone, are stored as FIT and GPX files on the device. They leave only when you share them or when you have turned on Strava upload.
- Voice control. Speech recognition is configured to run on-device, and commands are interpreted first by an offline grammar and then, if needed, by an on-device model (Apple Foundation Models or Gemini Nano). There is deliberately no cloud speech or cloud language tier — no audio and no transcript is sent to any server.
- Your settings, rules, saved locations and notification-forwarding configuration — unless you are a Plus rider and switch on Settings backup. Then a copy of your settings and rules (never your saved locations) is kept on our servers so you can restore it on another phone, until you switch the backup off again.
- Notifications forwarded to the bike computer (Android only). If you grant notification access, the app reads phone notifications in order to display them on the bike computer and passes them straight over Bluetooth. Their contents are not stored by the app and never reach a server.
- Everything the app does with the bike computer itself — pairing, route push, ride download, alerts on the screen — happens over a direct Bluetooth link between your phone and your device. No vendor cloud and no BikeOtter server sits in that path.
3. Your account
An account is required only for live tracking, ride-notification e-mails, the Strava link, route sync (saving a route on this website included) and the optional settings backup for Plus riders. Everything else works signed out.
You can sign in in one of two ways: a magic link sent to your e-mail address, or sign in with Strava. There is no password and no profile. What is stored is a user record held by our backend provider (Supabase) containing your e-mail address and sign-in timestamps, plus — for Strava sign-in — the Strava athlete id and display name.
Your e-mail address is used to identify you, and its local part (the piece before
the @) becomes the rider name shown to watchers of a live link. If your address
is [email protected], watchers see jane.doe. Bear that in
mind when choosing which address to sign in with.
To delete your account and everything attached to it, write to support@bikeotter.app from the address you sign in with. Deleting the account cascades: live-tracking sessions and their position points, group rides, messages watchers sent you, your saved contacts and their groups, the notification records, the Strava connection, your settings backup and your synced routes all go with it. There is no self-service button in the app yet — the deletion page gives the steps, the complete list of what goes, and what is kept afterwards.
The wishlist. Signed in — on the wishlist page or in the app — you can suggest a feature and vote for other riders' suggestions. A suggestion stores its title, the description you give and your account as its author; a vote stores which account voted for what. Until a suggestion is accepted, only you and we can see it. If you tick “You may contact me about this idea”, we keep that consent with the suggestion and, when your account has no address we can write to (a Strava sign-in has none), the address you give us for it. Both are used only to ask about or answer that one idea, and neither is ever shown publicly. We may also reply in your in-app support conversation, whether or not you ticked the box; as with any support reply, an e-mail pointing you to it goes out only if we have a real address for you. A note from the developer under a suggestion is public, like the suggestion itself. Deleting your account deletes your votes and erases the consent and the contact address automatically; a suggestion already on the list stays there, no longer linked to you.
3.1 Settings backup (Plus)
Off by default, and only if you switch it on. Settings backup is a BikeOtter Plus feature. Nothing is uploaded until you, signed in, switch it on under Settings → Settings backup and agree to what it stores. From then on the app keeps a copy of your settings on our backend — Supabase, the same provider and the same West EU (Ireland) region as everything else in §10 — so that after signing in on a new or a second phone you can restore them in one step. While it is on, the copy is refreshed automatically a few seconds after you change a setting, and Back up now refreshes it on demand.
What the copy contains:
- your units and your average riding speed;
- your body weight and your bikes and tyre setup, used for tyre-pressure advice;
- your skin type, used for the sunscreen reminder;
- your alert rules — presets and custom rules, and which of them are on;
- the list of apps allowed to forward notifications to the bike computer — package names only, never the contents of a notification;
- your heart-rate and power zone thresholds;
- the default turn-cue treatment, the route library's sort and filter, and the detour threshold for voice rerouting;
- your spoken-alert preferences;
- the live-sharing switches (share speed, share heart rate & power, allow messages), and the auto-go-live and push-riders-to-head-unit switches;
- the Strava auto-upload and upload-note preferences — only whether they are on, never a Strava token;
- whether the diagnostic log is on;
- the phone model the copy came from (for example “Pixel 8”), the app version, when you gave your consent and when the copy was last updated.
What it does not contain: your routes, your rides, your position, saved places, saved workouts, which bike computers or sensors you have paired, any account or Strava token, the contents of any notification, and the diagnostic log.
One copy per account. Each backup overwrites the previous one; there is no history. The database lets only your own account read it — not watchers, not other riders.
Deleting it. Switching Settings backup off deletes the copy from our servers immediately — that is how you withdraw your consent. Deleting your account deletes it too. Otherwise it has no automatic expiry. If your Plus subscription ends, no new backups are made; the existing copy stays until you switch the backup off or delete your account, and you can still switch it off — which deletes it — without Plus.
Why consent. Skin type and body weight can be read as data about your health, so the backup rests on your explicit consent (Art. 6(1)(a) and Art. 9(2)(a) GDPR, see §13). Switching it on is that consent; switching it off withdraws it.
3.2 Route sync
Off until you switch it on. Route sync keeps a copy of your routes in your BikeOtter account, so that the same library shows up in the app and in the route planner on this website (bikeotter.app/plan). In the app nothing is uploaded until you, signed in, switch it on under Settings → Cloud sync. On the website a route is stored when you save it while signed in, and once when you sign in: a route you planned while signed out and still have on screen is then saved to your account. Otherwise a route you plan stays in your browser (see §8). The copy is held by Supabase, in the same West EU (Ireland) region as everything else in §10.
What is stored for each route: the route the way the app itself stores it, which is the line with its elevation, the turn cues and the stops (POIs) along it, the surface along the way, the planned stops and routing profile if it was planned, any intervals and heart-rate plan, its name, whether you starred it, its turn-cue setting, where it came from (for example planned, a GPX import or Strava) and whether it was created on a phone or on the website, and a fingerprint of its content so that importing the same file again is recognised. Alongside it: a short summary (distance, climb, number of stops, start point and the map area it covers) so that the library can be listed without loading every route, a revision number and timestamps so that your devices can tell which copy is newer, and, once you ask the website to send a route to your bike computer, a flag telling your phone to put it on the bike computer the next time the two connect. Per account we also keep one timestamp: when the account last synced.
What stays on the phone: which bike computer a route was sent to and the app's link to the copy on that device, the map thumbnails in your library, and which route is active on your bike computer.
Plus and Free. With Plus, your whole library syncs. Without Plus, up to 10 routes are kept in the cloud: the ones you created on the website and the ones you choose to keep in the cloud in the app. Whether you have Plus is checked on our server, from your account id. If your Plus subscription ends, nothing is deleted: the routes already in the cloud stay, you can still open and delete them, and nothing beyond 10 is added.
Who can see it. The database lets only your own account read your cloud routes; not watchers, not other riders. Every change goes through one server function that checks who you are first. While the app is open it listens for changes to your routes, so that a route you save on the website shows up on the phone straight away.
How long it is kept. A synced route stays until you delete it, or until 24 months have passed without a sync from your account, from the app or the website; then all of the account's cloud routes are deleted, together with the timestamp of its last sync. Deleting a route removes its content at once. What is left is a marker (its id, a revision number, where it came from and when it was deleted) for 180 days, so that your other devices delete their copy too rather than uploading it again. Switching sync off stops syncing but does not delete what is already in the cloud. To take a route off our servers, choose Keep only on this phone on it in the app (it stays on your phone), or delete it on the website, which deletes it on your phone as well. Deleting your account deletes all of it (see the deletion page).
4. Live tracking
This is the one feature that publishes where you are. It is off unless you start it, and it ends when the ride does.
What a shared link is
Starting a live ride creates a session with a share token: 20 characters drawn from a cryptographic random source, giving a link of the form bikeotter.app/r/<token>. Anyone who has that link can watch, with no account and no sign-in. The link is the credential, so treat it like one — pass it to people you actually want watching. Watchers are shown only what is listed below; they are never given your e-mail address, your account id or the token of any other session.
A watcher's browser receives a short-lived access token scoped to that one session and capped at six hours. The database enforces this column by column: the session's owner and its share token are not readable by watchers at all.
The app shows you a live count of how many people are watching. It does not tell you who they are — no watcher identity is collected.
What a live point contains
Points are sent while you ride, throttled by time and distance. Each one carries:
| Field | Sent | Notes |
|---|---|---|
| Latitude, longitude | Always | The point of the feature. |
| Altitude, elapsed time, gradient, ride state | Always | Altitude is how high above sea level you are — the third coordinate of a position
you are already sharing, and the same reading the gradient beside it is worked out
from, so the two are not sent separately. Ride state is active,
paused, auto_paused or not_started, so the
page can show PAUSED rather than a lying LIVE badge. All four are
sent regardless of the two switches below, on purpose. |
| Lap and position on the lap | Only in a race | How many laps you have completed and how far you are into the current one, measured from the start/finish line. Worked out on your phone from the position above, so it says nothing the position does not. |
| Battery low | Only when low — no switch | A flag, not a percentage — this page never learns how much charge you have left, only whether it is running low. It is sent only while your phone's battery is low and not charging, so someone watching your dot can tell a dying phone from a lost signal. While it is set, the app also sends your position less often. |
| Speed, distance covered, climb so far, distance and ascent remaining, ETA | Only with “share speed” on — default on | Turn it off and none of these six are uploaded at all. “Climb so far” is the total metres you have climbed on this ride, which is a different figure from the altitude above: one is a running total, the other is where you are right now. |
| Heart rate, power, cadence | Only with “share heart rate & power” on — default off | Heart rate is health data. It is uploaded only if you switch this on, and the switch starts off. Cadence — how fast you are pedalling, in revolutions per minute — is governed by this same switch even though the switch is not named after it: it is a sensor reading of the same kind, and it says as much about your effort as power does. The switch in the app says so underneath it. |
What the session itself contains
Alongside the points: your rider name (see §3), the route's name, the planned route line, its total distance, the coordinates the route starts at, the two sharing switches above, whether messages are enabled, the session status and its timestamps, and — for a group ride — which group it belongs to.
When it ends, and when it is deleted
A session expires at whichever of these comes first, and expiry is checked every minute:
- the expiry time set when you started it — six hours by default;
- 45 minutes after the last point or keep-alive from the app, so a forgotten ride does not stay “live” all evening;
- 60 minutes after it was created, if no position ever arrived.
Deletion then follows automatically:
- The session record is deleted 7 days after it ended or expired, taking anything still attached to it with it.
- Your position points are deleted with it — the same 7 days, not a moment longer. They used to be swept after 24 hours, ahead of the session; they are now kept for the whole of the session's own life so that a ride whose bike computer lost its recording can still be rebuilt from the live track inside the app. Nothing else about the sweep changed, and the outside bound on how long a shared ride is stored is unchanged at 7 days.
Group rides work the same way once the ride is under way: a group link is valid for 12 hours after it goes live, holds at most 50 riders (15 in a race), and the group record is deleted 7 days after it ends. A ride you plan ahead of time is different: the link — and the names of everyone who has said they are coming — stays joinable for up to 30 days before anyone actually sets off; the 12-hour clock does not start until the first rider goes live. Ending a share from the app stops the upload immediately; the sweeps then clear the stored data on the schedule above.
A group ride can be a race. Each racer's phone then also writes that racer's lap times to a record of its own, together with the race's name and the rider name shown on the roster. Those lap times can be read by the racers in that race and — only while the group ride still exists — by anyone holding its link. They are deleted 90 days after they last change, which is longer than the group ride itself is kept, so that every racer can still look back at the results.
A group ride can also be created by a partner app, currently Ride Alert, where organisers post group rides for their riders. The partner sends us the ride's title, its start time, optionally a route, optionally the organiser's display name (shown as “Led by …”) and a link back to the ride on its own site; a ride created this way can be planned up to 366 days ahead. The partner gets nothing about the riders back: we send it only how many riders have joined and how many are live. Joining still happens in the BikeOtter app with a BikeOtter account, and nothing about your account reaches the partner. The partner can also embed a watch-only map of the ride on its own page; it shows the route and, while the ride is under way, each rider's live position marked with their initials instead of their name. The embedded map never receives a rider's name: it reads the ride with narrower access than the group link, which covers positions and the route but no names, and the initials are worked out on our server. A ride created by a partner is kept and deleted exactly like any other group ride (above).
5. Messages from watchers
If you enable messages, someone who reached your link through one of your notification e-mails can send you short messages, which appear on your bike computer. A general watcher who merely has the link cannot — sending requires a per-contact token that only the mailed link carries.
A message stores its text, the sending contact and a timestamp. Senders are limited to three messages per hour. Messages are attached to the session and are deleted with it — so within the same 7-day window as §4. Messages are stored in readable form on the server; they are not end-to-end encrypted.
6. Ride-notification e-mails
You can save contacts so that starting a live ride e-mails them the link. Nothing is sent unless you pick a group when you go live; choosing “nobody this ride” sends nothing.
What is stored per contact: the e-mail address (lower-cased), an optional name, an unsubscribe token, a message token, and — if applicable — when they unsubscribed or when mail to them hard-bounced. Contacts are visible only to you; the database denies anonymous access to them entirely.
What the e-mail contains and reveals: your rider name, the route name and
distance, the watch link, when the link expires, and an unsubscribe link. It is sent from
[email protected] by a Cloudflare Worker on our behalf, and its
Reply-To is set to your own e-mail address so that a recipient
can answer you directly — which means your recipients can see the address you signed in
with.
The arrival e-mail (optional, and off until you ask for it): switch on “Tell them when you get back” for a contact group and the people who were mailed that ride's link — only those, and only if the link e-mail actually reached them — get one short note when the ride finishes: that you finished, the distance and moving time the ride published, the time you got in, and the same watch link. On a ride with a route loaded, you can also get an optional heads-up roughly fifteen minutes before the estimated arrival. Distance is included only if “Speed & distance” sharing was on for that ride: the figures are read back from what the ride actually published, never reconstructed from the route you planned. A session that merely expires or times out sends nothing — an expiry is not an arrival. Neither note carries the message token, because the ride is over.
Limits: at most one e-mail of each kind per contact per ride — the link, the optional heads-up and the arrival note (a contact cannot be mailed the same kind twice for the same session), at most 50 members in a group, and at most 200 notification e-mails per rider per rolling 24 hours.
Unsubscribing: every e-mail carries a footer unsubscribe link and standard one-click unsubscribe headers, so a mail client's own “unsubscribe” button works. An unsubscribe needs no account and stops all further ride notifications to that address.
Your responsibility: when you add someone else's e-mail address you are asking us to mail a person who has not dealt with us. Add only people who expect to hear from you. Contacts have no automatic expiry — they are kept until you delete the contact or your account.
Race invites: when you set up a race you can invite contacts as racers or as
spectators. Each invite is recorded — which contact, which race, racer or spectator, and
when it was sent — so that nobody is mailed twice; the record is visible only to you and is
deleted with the race's group ride, 7 days after it ends. The invite comes from
[email protected] under your name, with its Reply-To set to
your own e-mail address. A racer's invite carries your name, the race's name, start
time, laps and loop length, a picture of the route on a map, the race link and a short
description of what BikeOtter does in a race; a spectator's invite carries your name, the
race's name and start time, and the watch link. Both carry the same unsubscribe link as
every other mail. At most 15 racers and 30 spectators can be invited per race, and
invites count toward the same 200 e-mails per rolling 24 hours.
7. Strava
Linking Strava is optional. Authorisation happens in your system browser on Strava's own pages; BikeOtter never sees your Strava password.
- Permissions requested:
read,read_all,activity:read_allandactivity:write— enough to list and import your routes and activities and to upload rides. - Where the tokens live: your Strava access and refresh tokens are stored server-side only, in our backend, and are readable by nothing except the server function that uses them. The phone holds only a short-lived value kept in memory during the sign-in handshake, never written to disk.
- What goes up: the ride file itself (a compressed FIT), plus an optional name and description, when you upload a ride.
- What comes down: your Strava routes and activities, GPX exports of routes, and the position/altitude/time streams of an activity when you import it as a route. Responses are cached against your account and deleted after 48 hours.
- Disconnecting revokes the token at Strava and removes the stored connection. Until you disconnect, the connection record persists — it has no automatic expiry.
What Strava then does with your data is governed by Strava's own privacy policy. Strava is a US company and using it involves a transfer of data to the United States.
8. Weather, POI, geocoding, routing and maps
Several features need to ask an outside service about a place. There is a meaningful distinction in how they are asked:
- Through our backend — weather forecasts, POI search, geocoding, and everything Strava. Your phone asks our server function. For weather, geocoding and Strava the server function then asks the outside service, which therefore sees the coordinates or search terms, but not your IP address. POI search asks no outside service at all: it is answered from our own copy of OpenStreetMap data (see below).
- Directly from your phone — route calculation (BRouter) and map tiles (the OpenStreetMap tile server). Those services receive the request from your device, so they see your IP address along with the coordinates or the map area you are looking at, and may log it under their own policies.
- Through our routing proxy, from the route planner on this website
(bikeotter.app/plan). A browser on this site cannot ask BRouter
directly, so the points you place and the profile you chose go to our own routing proxy at
map.bikeotter.app, a Cloudflare Worker, which asks BRouter (brouter.de) and hands the answer back. BRouter therefore sees the coordinates and the profile, but not your IP address. The proxy keeps each answer for up to 24 hours, keyed by the points and the profile, so the same route is not asked for twice; it uses your IP address only to count requests for a rate limit, and stores no record of who asked. Place search and the names shown for your stops go to the same geocoding server function as in the app, described above.
Planning on this website needs no account, and nothing you plan reaches our servers until you save it. Apart from the short-lived caches described here, which hold places and routes rather than people, nothing you plan reaches our storage. The route you are drawing is kept only in your own browser (see §15) until you export it as a GPX file, which is saved to your device and sent nowhere, or sign in and save it, which stores it with your routes as described in §3.2.
Your current location, on this website, is asked for only when you press the location button on the route planner's map or "Add my location", and your browser asks you first. The position is used in your browser to centre the map; if you add it, it becomes a stop like any other, sent to work out the route as described above. We do not store it.
Stops along the route, on this website, are found only when you are signed in, through the same POI search function as in the app, described above. The request carries the line of the route, the categories you picked and your account id. The account id lets the function check whether you have Plus and count free goes per account rather than per browser (see the next paragraph).
Free goes. POI search, weather, place search and hosting a group ride are Plus features that can be tried a few times without Plus. To count those goes, the app sends a random identifier that it creates on your phone and keeps in the phone's secure storage, together with your RevenueCat customer id so that our server can ask RevenueCat whether you have Plus (see §10). Our server keeps one small record per identifier and feature: how many goes are spent, and when that last changed. The identifier is not linked to your account, so the record has no automatic expiry and cannot be matched to you when you delete your account; it says nothing beyond how often one installation used a feature. On this website the count is kept against your account id instead, and that record is deleted together with your account.
Weather and geocoding answers are cached on our side so repeated lookups do not re-ask: weather for 2 hours, geocoding for about a week. Caches are keyed by place, not by rider.
Where POIs come from. POI search is answered from a table in our own database (Supabase, see §10) holding about 10 million points of interest, such as drinking water, food, toilets and bike shops, taken from an extract of the whole OpenStreetMap database. We refresh it by hand from a newer extract from time to time, not on a fixed schedule, so a place added to OpenStreetMap recently may not be there yet. The search area (a point and a radius, or the line of a route) and the categories go no further than our server, and the answers are not cached.
9. The diagnostic log
The app keeps a technical log to make Bluetooth and support problems reportable.
- It is on by default. A rider who hits a problem has a log to attach without having had the foresight to turn recording on first. Turn it off any time in Settings → Diagnostics.
- Passwords, tokens and API keys are removed before anything is written — a bearer token, API key, magic-link token or OAuth code appearing anywhere in the log becomes a one-way marker, not the credential itself.
- It stays on the phone until you attach it to a support request. Two rotating files in the app's own storage; nothing leaves the phone before that. There is no mail composer step — a support request is sent from inside the app itself, as a message in an ongoing support thread (see the next bullet). Attaching the log there uploads it to a private storage bucket, and that uploaded copy is deleted after 180 days. You can clear the on-phone copy, or turn logging off, at any time in Settings → Diagnostics.
- A support request is a thread, not a one-off e-mail. Whatever you write — with or without a log attached — is stored as part of an ongoing support conversation tied to your account and your sign-in e-mail address. It is readable by BikeOtter staff answering support requests, and by nobody else. The conversation itself is kept until you delete your account, at which point it is deleted with it (see the deletion page); an uploaded log is on its own 180-day clock regardless, independent of the account.
- A screenshot you attach yourself is stored the same way. The support composer can take one image per message, picked by you from your phone's photo library — never read automatically, and never taken from your gallery in the background. What you picked is uploaded to a separate private storage bucket, is readable by BikeOtter staff answering support requests and by nobody else, and is deleted after 180 days on the same clock as an uploaded log. A screenshot may show whatever happened to be on your screen, so have a look before you attach it; you can take it off again in the composer up until you send the message.
- Feedback left without an account is genuinely anonymous. The home-screen Leave feedback shortcut does not ask you to sign in. What is stored is what you wrote, the app version and platform, a random identifier generated on your phone that exists only so we can rate-limit abuse, and — only if you choose to type one — an e-mail address so we can reply. Leave that field blank and we have no way to connect the message to you: not to an account, not to a name, not to a device we could identify. It is readable by BikeOtter staff and by nobody else.
- The honest consequence of that anonymity: if you left no address, we cannot identify a feedback message as yours, which means we cannot delete it on request either — there is nothing to match you against. If you want that option, either leave an address or use the support conversation instead, which is tied to your account and goes when the account does.
- What is in it: app version and build, phone model, operating system version, locale and time zone, plus a technical trace of device connections and app events. Live-share tokens are truncated before being written. It can contain position coordinates — at least one device feature logs the rider's latitude and longitude — plus route coordinates, saved places and device serial numbers. That is not redacted, so treat a diagnostic log as data about you, and only send one to someone you trust.
10. Third parties we use
The complete list of outside services the app, the backend and this site contact. There are no others, and in particular there is no analytics, attribution, advertising or crash-reporting service anywhere in the product.
| Service | Used for | What it receives |
|---|---|---|
| Supabase | Database, sign-in, server functions and the realtime feed behind live tracking and route sync | Everything described in §3–§8 that is stored at all, plus the connection metadata any host sees. Hosted in the EU — the project runs in Supabase's West EU (Ireland) region, so this data is stored inside the EEA. |
| Cloudflare | Hosting for bikeotter.app and the viewer pages;
the Worker that sends ride-notification e-mails; the map server and the routing proxy for
this site's route planner at map.bikeotter.app | Requests to this site and to the mail endpoint, including IP address, as part of serving and protecting them. For the route planner, also the points you place and the profile you chose (see §8). Worker request logs are retained under Cloudflare's own defaults. |
| Open-Meteo | Weather forecasts | Coordinates and times, sent by our server, not your phone. |
Photon (photon.komoot.io) and Nominatim
(nominatim.openstreetmap.org) | Turning place names into coordinates and back | The search term or coordinates, sent by our server. |
BRouter (brouter.de) | Calculating a route between your waypoints | Your waypoint coordinates and the chosen profile — sent directly by your phone, so it sees your IP address. From the route planner on this website they are sent by our routing proxy instead, so BRouter does not see your IP address there. |
| OpenStreetMap tile server | Map imagery in the app and on the viewer page | Which map tiles you are looking at — requested directly, so it sees your IP address. |
| Strava | Optional route/activity import and ride upload | See §7. United States. |
| RevenueCat (RevenueCat, Inc.) | Plus purchases, and checking whether you have Plus | From the app, directly and on every launch: your RevenueCat customer id (a random id until you sign in, then your account id), the purchases and receipts from the App Store or Google Play, and the usual app and device details such as platform, operating system and app version. Requested directly, so it sees your IP address. From our server, when a feature needs to know whether you have Plus: that customer id (from this website, your account id). We keep the answer, yes or no, with the time we asked, and ask again after 10 minutes. United States. |
| Shorebird | Over-the-air delivery of code fixes to the installed app | An update check on launch. See §10.1 — it is not optional. |
| YouTube (Google Ireland Limited) | Playing the two videos on this site's home page — and only once you press play | Your IP address, the page you pressed play on and the usual browser details — requested directly by your browser from youtube-nocookie.com, so Google sees your IP address. See §15. |
The app stores are separate: if you install BikeOtter from Apple's App Store or Google Play, that store's own account, purchase and crash-reporting arrangements apply between you and them, and are outside our control.
10.1 Shorebird, and why it contacts a server without asking
BikeOtter is released through Shorebird, which lets us ship a fix to the app's Dart code over the air, between store releases. It is the mechanism behind a patch arriving without a store update.
The part you should know: the app checks for a patch on launch, automatically, and there is no setting to turn it off. Our configuration does not disable the automatic check, and the app offers no opt-out — the only way to stop it is not to run the app. We would rather say that plainly than bury it.
We do not operate Shorebird's servers and cannot observe what its updater sends, because the updater is built into the app's runtime rather than into code we write. What such a check necessarily involves, though, is not a matter of opinion: to be answered at all it must identify which app is asking (our Shorebird app id, which is not secret and is the same for every install) and which version and patch level is already installed, and — like any network request — it reaches Shorebird's servers from your IP address. Assume Shorebird can see at least that much, and that it may log it as any host logs requests.
Two things we could not establish and will not guess at: the exact contents of that request beyond the above, and the country its servers sit in. If you need either before installing, ask us and we will get Shorebird's own answer in writing rather than speculate here.
What we can rule out: the check is not tied to your account, and BikeOtter works signed out, so the request carries no identity we have given it. A patch changes the app's code — never your data, your rides or your routes.
11. Phone permissions
The app asks for as little as it can, and each permission is used for exactly one thing.
| Permission | Why |
|---|---|
| Bluetooth | To find and talk to your bike computer and sensors. On Android the scan permission is declared as never being used to derive location. |
| Location | Coarse location on Android, “while using the app” on iOS: to search for POIs near you and to start a reroute from where you are. Background location is not requested on either platform. During a ride the position that gets shared comes from the bike computer over Bluetooth. |
| Microphone and speech recognition | Voice commands. Recognition runs on-device; audio is not sent anywhere. |
| Notifications | To show the ride's ongoing notification and alerts. |
| Notification access (Android only) | Optional. Lets the app read incoming phone notifications so it can display them on your bike computer. You grant it yourself in system settings, and their contents are never stored or uploaded. |
| Run at startup / battery exemption (Android only) | So an interrupted ride can resume after a reboot and is not killed mid-ride. |
The app does not ask for photos, camera, your phone's contact list, calendar, or any advertising identifier, and it does not use Apple's tracking permission because it does not track.
12. Retention at a glance
| Data | Kept for |
|---|---|
| Live position points | 7 days after the ride ends or expires — deleted with their session |
| Live session record | 7 days after it ends or expires |
| Group ride record | 7 days after it ends or expires |
| Race lap times | 90 days after they last change — kept after the group ride itself is deleted |
| Race invites (who you invited) | Deleted with the race's group ride — 7 days after it ends or expires |
| Messages from watchers | Deleted with their session — so within the same 7 days |
| Weather cache | 2 hours |
| Geocoding cache | 8 days |
| Route cache of the website route planner's proxy | Up to 24 hours |
| Strava response cache | 48 hours |
| Contacts and their notification records | Until you delete the contact or your account — no automatic expiry |
| Strava connection | Until you disconnect or delete your account |
| Free-goes counter (see §8) | In the app: kept against an identifier on your phone, not your account, with no automatic expiry. On this website: until you delete your account |
| Our record of whether you have Plus (from RevenueCat) | Checked again after 10 minutes when it is needed. A record for your account id is deleted with your account; one for the random id used before you sign in has no automatic expiry |
| Synced routes (route sync, or saved on this website) and when you last synced | Until you delete them or your account, or 24 months after your last sync, whichever comes first |
| Marker left by a route you deleted from the cloud | 180 days, so that your other devices delete their copy too |
| Settings backup (Plus, only if you switched it on) | Until you switch the backup off — which deletes it immediately — or delete your account; no automatic expiry |
| Account record | Until you ask us to delete it — see how to delete your account |
| Support conversation (thread and messages) | Until you delete your account — see how to delete your account |
| Wishlist contact address (only if you opted in) | Until you delete your account |
| Anonymous feedback (home-screen shortcut) | Kept until we have acted on it — no automatic expiry. If you left no reply address it cannot be identified as yours, so it cannot be deleted on request |
| Diagnostic log | On your phone by default, rotated automatically, deletable by you at any time; if attached to a support request, the uploaded copy is kept 180 days on its own clock, independent of the account |
| Screenshot attached to a support message | 180 days, on its own clock, independent of the account |
Server and platform logs kept by our hosting providers (Supabase, Cloudflare) follow those providers' own retention defaults and may briefly contain IP addresses as an unavoidable part of serving a request.
13. Legal bases
- Art. 6(1)(b) GDPR — performing what you asked for. Signing you in, running a live share you started, sending the notification e-mails you requested, uploading a ride to a Strava account you linked, calculating a route you drew, keeping the routes you synced or saved on this website, checking whether you have Plus and counting your free goes, and sending a support request with the diagnostic log attached.
- Art. 9(2)(a) GDPR — explicit consent for health data. Heart rate and power are health data. They are uploaded only when you switch “share heart rate & power” on; the switch is off by default and switching it off stops the upload. Cadence is uploaded under that same switch. We do not claim cadence is health data in the Art. 9 sense — it is a reading off a crank sensor, not off your body — but it belongs to the same family and gets the same protection rather than a weaker one.
- Art. 6(1)(a) and Art. 9(2)(a) GDPR — explicit consent, for Settings backup. A copy of your settings is uploaded only after you, as a Plus rider, switch Settings backup on; it is off by default. Because the copy includes your skin type and body weight, which can be read as health data, we treat switching it on as explicit consent in the Art. 9 sense. Switching it off withdraws that consent and deletes the copy. See §3.1.
- Art. 6(1)(a) GDPR (and, for anything the player stores in your browser, § 25(1) TDDDG) — consent, for the videos on the home page. Pressing play on a video is the request to load YouTube's player, and nothing from YouTube loads before it. You withdraw it simply by not pressing play again: leaving or reloading the page removes the player.
- § 25(2) No. 2 TDDDG — strictly necessary storage in your browser, for the few entries this site keeps in your browser's local storage: the language and theme you chose, what the demo leaves behind, a sign-in on the wishlist or in the route planner (with its one-time Strava code), and the route you are drawing in the route planner, with which of your saved routes it is. §15 lists each one. No consent is needed for these, and none is asked for.
- Art. 6(1)(f) GDPR — legitimate interests in keeping the service working and unabused: rate limits, one-mail-per-contact-per-ride guards, bounce handling, the minimal request logging our hosts perform, and on-device diagnostic logging by default so a support request can include one — you can turn it off in Settings → Diagnostics at any time.
Withdrawing consent is always possible and takes effect going forward: end the share, turn the heart-rate/power switch off, turn the log off, disconnect Strava, delete the contact, switch Settings backup off, delete a synced route or keep it only on your phone.
14. Your rights
Under the GDPR you have the right to access your data (Art. 15), to have it corrected (Art. 16) or erased (Art. 17), to restrict processing (Art. 18), to receive it in a portable form (Art. 20), and to object to processing based on legitimate interests (Art. 21). Where processing rests on consent, you may withdraw it at any time.
Write to support@bikeotter.app and we will handle it. Much of it you can also do yourself in the app: end a share, delete a contact, disconnect Strava, clear the diagnostic log, switch Settings backup off (which deletes the copy on our servers), delete a synced route or keep it only on your phone.
Erasure (Art. 17) has its own page, because it deserves the detail: how to delete your account — the steps, what is erased with it, what is kept afterwards and for how long.
If you think we have got this wrong, you may complain to a data protection supervisory authority — in the EU, the one where you live, where you work, or where the alleged infringement took place (Art. 77 GDPR).
15. This website
bikeotter.app is a set of static pages hosted on Cloudflare. It sets no cookies and runs no analytics. It does keep a few small entries in your browser's local storage, each one written because of something you chose or a feature you used. All but two of them never leave your browser: they are read by the page itself and by nothing else — not by us, not by anyone. The two that do exist only if you sign in, on the wishlist page or in the route planner: they are sent to our backend, because that is how signing in works. The complete list:
| Entry (key) | What it holds, and why | Sent anywhere? |
|---|---|---|
bikeotter:lang | A language code, for example de. Written when you pick a language at the foot of a page — or on your first visit to an English page, if your browser asks for German, Spanish, French, Italian or Polish: the site then switches you to that language once, and remembers that it has, so it never switches you again against a choice you made. | No |
bikeotter-site-theme | light or dark. Written only when you press the light/dark button in the header, so that the next page opens in the theme you picked. Until you press it nothing is stored, and pages follow your system setting. | No |
FlutterSecureStorage and FlutterSecureStorage.plus_device_key | Only from the demo at /demo/, and only once you start a group ride in it: a random identifier, encrypted with a key kept beside it. The demo is the real app, which creates this identifier when you start a group ride; in the demo that ride is simulated inside your browser, so the identifier is used for nothing and simply stays behind. | No |
sb-ccskijubebzhwpknjkpl-auth-token | Only if you sign in on the wishlist page or in the route planner: your sign-in session — an access token, a refresh token, and your account's user id and e-mail address — so that you are still signed in when you come back. | Yes, to our backend (Supabase, see §10), with each request the wishlist page or the route planner makes while you are signed in — that is how it knows a vote, a suggestion or a saved route is yours |
bikeotter.strava.web.pending | Only while you sign in to the route planner with Strava: a random one-time code, made in your browser when you press “Continue with Strava” and kept for the moments you spend on Strava's page. It proves to our backend that the sign-in coming back from Strava is the one this browser started. It is kept in that tab's session storage, which your browser empties when you close the tab, and deleted as soon as the sign-in finishes. | Yes, once, to our backend (Supabase, see §10), to finish that sign-in. When you start, only a fingerprint of it (a SHA-256 hash) is sent |
bikeotter.planner.cloud.v1 | Only if you sign in to the route planner: your account's user id, the id and revision number of the saved route you have open (empty for a route not saved yet), and whether it has edits you have not saved. It lets a reload reopen the same saved route, and keeps a route you drew before signing in from being saved twice. It is rewritten when you open, save or edit a route, and deleted when you sign out of the route planner. | No. Saving a route sends its id and revision to our backend (see §3.2), but this entry itself never leaves your browser |
bikeotter.planner.draft.v1 | Only if you use the route planner at bikeotter.app/plan: the route you are drawing (its stops and their names, the profile, whether it goes back to the start, and when it was last saved) or a GPX file you imported, so that reloading the page or closing the tab does not lose it. It is overwritten as you edit, and stays until you clear this site's data in your browser. | No. The points are sent to work out the route (see §8), but this entry itself never leaves your browser |
bikeotter.planner.poiTypes.v1 | Only if you search for stops along the route in the route planner: which categories you have switched on (drinking water, food, coffee and so on), so that the next search looks for the same ones. It is rewritten when you switch a category on or off, and stays until you clear this site's data in your browser. | No. The categories are sent with each search (see §8), but this entry itself never leaves your browser |
To remove them, clear this site's data in your browser — in most browsers through the icon to the left of the address bar, or under the settings for cookies and site data. A private window starts with none of them and forgets them when you close it. If your browser blocks site data, pages still work: they follow your system's language and theme, and simply cannot remember a choice.
Why you are not asked first. Storing and reading these entries needs no consent under § 25(2) No. 2 TDDDG, because each is strictly necessary for something you asked this site for: pages in your language and in the theme you picked, the demo you opened, the route you are planning, and staying signed in on the wishlist or in the route planner. The sign-in session is personal data, and for it the basis is Art. 6(1)(b) GDPR (§13). There is nothing else here to consent to, which is why you are not being asked. The one exception is a video on the home page, described below: pressing its play button is the consent.
Every asset a page here needs is served from this site. The typefaces (Archivo and Geist Mono) are hosted by us rather than fetched from a font CDN, precisely so that reading a page does not hand your IP address to a third party. There is no tag manager, no share widget, no web font service, and no video player until you ask for one. The only party that necessarily sees your request is Cloudflare, which hosts the pages — unavoidable, since something has to serve them.
The videos on the home page are the one exception, and only once you press play. The home page shows two BikeOtter videos that are hosted on YouTube. What loads with the page is a preview image and a play button, both served from this site; no request goes to YouTube or Google until you press play. Pressing play replaces the preview with YouTube's player, loaded from youtube-nocookie.com — YouTube's privacy-enhanced mode, operated by Google Ireland Limited, Gordon House, Barrow Street, Dublin 4, Ireland. From that moment your browser talks to Google directly: Google receives your IP address, the address of the page and the usual browser details, and while the video plays the player can store identifiers in your browser and send information about the playback to Google, which may also process it in the United States (Google LLC is certified under the EU–US Data Privacy Framework). Privacy-enhanced mode means YouTube does not use your viewing of an embedded video to personalise what it shows you elsewhere on YouTube — but it is not anonymous. We receive nothing from any of this. Google's own privacy policy applies: policies.google.com/privacy. If you do not press play, none of it happens. The “Watch on YouTube” link under each video opens it on youtube.com instead, where YouTube's usual terms apply.
The live-tracking viewer at bikeotter.app/r/… and the group viewer at /g/… and the watch-only map a partner embeds at /w/… additionally load the shared ride's data from our backend and map tiles from OpenStreetMap. Opening a viewer link deliberately keeps no session in your browser: the access token it uses is held in memory for that visit only and is not persisted. Watchers are counted, not identified.
The route planner at bikeotter.app/plan additionally loads its map
from our own map server at map.bikeotter.app, and sends the points you place to
our routing proxy and what you type into its search box to our geocoding function, as
described in §8. It works without an account and stores nothing on our servers
unless you sign in and save a route (§3.2). Signed in, it also loads your
saved routes from our backend and finds stops along the route through our POI search
function (§8).
Viewer links are excluded from search engines by robots.txt, and each carries
a noindex instruction, so a shared ride is not meant to turn up in search
results.
16. Children
BikeOtter is not directed at children and is not intended for use by anyone under 16. We do not knowingly collect data from children. If you believe a child has used the app with an account, write to us and we will delete it.
17. Changes
The app is young and still changing. If what it collects changes, this page changes with it, and the version and date at the top move. Material changes will be pointed out in the app rather than slipped in quietly.
18. Contact
Questions, requests, or a correction to something on this page: support@bikeotter.app.
See also the terms of use and safety disclaimer and the imprint.