Introduction#
I have always appreciated the effort and development that goes into privacy preserving applications. Many apps exist in this category, such as Signal, Tor Browser and Aurora Store, and the two I want to focus on are NewPipe and Vela Maps. I believe these are two great examples, as they aim to provide a major improvement in user privacy. They do provide major improvements, but there are levels of privacy, and there are ways to correlate and determine with a high degree of confidence that it is the same person behind an earlier session or a signed-in account, using fingerprinting techniques. What they give is pseudonymity, not anonymity. In this blog post my objectives are to understand the challenges in trying to use mainstream applications, what the privacy issues with them are, and how we can overcome them with technical means. This post will be broken down into three sections: first, the identifiers Google and YouTube collect at each layer of the phone and how they can be correlated; second, what Vela Maps and NewPipe each improve, and whether Google can still identify the user through them; and third, how the operating system, user profiles, a virtual private network (VPN) or Tor, other privacy technologies and the user’s own behaviour can overcome these privacy issues while keeping the experience exactly or close to how the default apps are.
Identifiers and Correlation#
Anonymity can be defined as a person not being identifiable within a set of people. That is stricter than having no account. In Pfitzmann and Hansen’s terminology the definition reads: “Anonymity of a subject means that the subject is not identifiable within a set of subjects, the anonymity set.” A person is anonymous only when an observer cannot tell their requests from those of everyone else in that set. The main observer here is Google, which can correlate requests, relating them to each other, or link them to an identity or a Google Account. In European law the General Data Protection Regulation (GDPR) sets a similar bar. Recital 26 counts singling out among the means of identifying a person and Recital 30 warns that internet protocol addresses and cookie identifiers leave traces that, combined with other information, may be used to profile and identify people. Singling someone out does not need a name. Pfitzmann and Hansen define a pseudonym as an identifier other than a real name, and pseudonymity as acting under one, which is why having no account can leave a person pseudonymous rather than anonymous. These are the levels of privacy this post measures each app against: identified through an account, pseudonymous under an identifier, and anonymous within a set.
Google’s own apps, YouTube and Maps among them, give it identifiers at several layers of the phone: the account, the app, the device and the network. Signing out removes only the top layer, the Google Account. Google’s privacy policy, in force since 1 October 2026, says that “when you’re not signed in to a Google Account, we store the information we collect with unique identifiers tied to the browser, application, or device you’re using.” Being signed out is therefore not the same as being unidentifiable. The same policy lists what else it collects: unique identifiers, device type and settings, mobile network information including the carrier name and phone number, and the Internet Protocol (IP) address of each request. Beneath Google’s apps, Android and Google Play services add two more. The advertising ID comes from Google Play services and can be reset by the user, and ANDROID_ID is unique for each combination of app signing key, user and device. Thus, the account is one identifier among several, and a privacy preserving application that has no account but still talks to Google sends the IP address of every request.
Android stops ordinary apps from reading the phone’s hardware identifiers but still gives every app the SIM’s country and carrier without a permission. Android 10 put the International Mobile Equipment Identity (IMEI) and serial numbers of the phone and its SIM behind the permission READ_PRIVILEGED_PHONE_STATE, which ordinary apps do not hold. This restriction moves apps to scoped or resettable values such as ANDROID_ID and the advertising ID. The country stays open, because the Android source of November 2025 puts no permission on getSimCountryIso, getSimOperator or getNetworkCountryIso. No source I read shows NewPipe or Vela sending these values, but any app can read them, so the carrier and its country sit beside the other identifiers at this layer.
For that IP address to identify the user, Google has to combine it with other signals. A signed-in app on the same address can supply the strongest of them, the Google Account. Without such a signal an IP address is weak. Cloudflare reports that carrier-grade network address translation can let one address stand for hundreds or even thousands of users. Google, explaining IP Protection in Chrome, says IP addresses are “cheap to collect, relatively stable over time and, combined with other signals, can be used to identify an individual device.” On GrapheneOS, the Android-based operating system I run, those signals can come from other apps on the phone. When NewPipe or Vela Maps shares an IP address with apps signed in to a Google Account, requests with an account and requests without one arrive from that address together. However, none of the sources I read shows Google linking signed-out requests to an account this way. The link also weakens when the address is a VPN exit IP (the address services see instead of the phone’s) that, like Mullvad’s, many strangers share. The shared address is still where the link starts, because anyone who sees both kinds of request can place a front-end with no account, such as NewPipe or Vela Maps, behind the same address as a signed-in app simultaneously.
That starting point takes one moment, but the order of operations plays out over a history. By the order of operations I mean what the user does on one device or IP address, and in what sequence. The history matters because correlation works across many visits, not only inside the current session. The UK Information Commissioner’s Office describes fingerprinting as involving “the collection of pieces of information about a device’s software or hardware, which, when combined, can uniquely identify a particular device and user.” Because the pieces identify a device and user when combined, no single piece of information has to be unique. The World Wide Web Consortium adds that fingerprinting lets a party correlate multiple visits into a profile or history of the user. Histories are distinctive even when short. Olejnik, Castelluccia and Janc found that users with at least four detectable visited websites were uniquely identified by their histories in 97% of cases. All of this assumes that Google keeps the history long enough to match against. Its retention policy removes part of the IP address from advertising data in its logs after 9 months and cookie information after 18 months. Until those periods end, the current session can single the user out, and so can their history on a device or IP address.
Some fingerprinting needs no code on the phone at all, because the headers and the Transport Layer Security (TLS) connection of an ordinary request can identify the client software. The World Wide Web Consortium calls this passive fingerprinting, which rests on “characteristics observable in the contents of Web requests, without the use of any code executed on the client”. The connection is the clearest case. Before any encryption starts, a TLS client sends a ClientHello that lists the versions, cipher suites and extensions it supports. Even the server’s name in it “is carried in cleartext”, as RFC 8744 notes, so an observer on the path reads which service the phone is talking to. In 2017 Salesforce published JA3, which joins five of the ClientHello’s fields and hashes them so that a server can identify the client application by how it connects rather than by what it says:
import hashlib
# JA3: five ClientHello fields as decimals (Salesforce's own example)
version = 769 # TLS 1.0
ciphers = [47, 53, 5, 10, 49161, 49162, 49171, 49172, 50, 56, 19, 4]
extensions = [0, 10, 11]
curves = [23, 24, 25]
point_formats = [0]
fields = [str(version)] + ["-".join(map(str, f)) for f in (ciphers, extensions, curves, point_formats)]
ja3 = ",".join(fields)
print(ja3)
print(hashlib.md5(ja3.encode()).hexdigest()) # ada70206e40642a3e4461f35503241d5
None of these fields is secret or identifies the user, because they describe only the client software.
The fingerprint separates programs, and two programs on one machine are two clients to the server. I ran ja3_local.py, which builds the same string from a live ClientHello, against curl and Python on one laptop, both using OpenSSL 3.5.8 and both sending the same server name, and they produced two different hashes:
# Rerun on 9 October 2026 with curl 8.18.0, Python 3.14.8 and OpenSSL 3.5.9.
# Both JA3 strings and hashes are byte-identical to the published laptop run.
curl 8.18.0
771,4866-4867-4865-4868-49196-49200-52393-52392-49325-49195-49199-49324-49187-49191-49162-49172-49161-49171-157-49309-156-49308-61-60-53-47-159-52394-49311-158-49310-107-103-57-51,65281-0-11-10-16-22-23-49-13-43-45-51-27,4588-4587-4589-29-23-30-25-24-256-257-258-259-260,0-1-2
42cb4ba4c818da3ce6424cb212377c24
t13d3513h2_bfa337485184_8d7351bd871b
python 3.14.8
771,4866-4867-4865-4868-49196-49200-52393-52392-49325-49195-49199-49324-49187-49191-49162-49172-49161-49171-157-49309-156-49308-61-60-53-47-159-52394-49311-158-49310-107-103-57-51,65281-0-11-10-35-22-23-13-43-45-51-27,4588-4587-4589-29-23-30-25-24-256-257-258-259-260,0-1-2
79528b91a7d3b362447f5c890f9fb708
t13d351200_bfa337485184_a141b6f9fa1c
JA3 hashes the extensions in the order a client sends them, so a client that shuffles that order changes its JA3 but keeps its JA4. JA4, FoxIO’s successor to JA3, sorts the extensions before hashing, which removes their order from the fingerprint. Chrome 110, released in 2023, began shuffling Chrome’s extensions on desktop, on Android and in WebView. Google’s explainer states that “This is not designed to prevent all fingerprint of TLS stacks.” In the rerun, whose JA3 strings matched the laptop’s byte for byte, the two JA4 values share their cipher hash and differ because curl alone sends extensions 16 and 49 and Python alone sends 35. As a result, a client can be identified by which extensions it sends rather than by their order, which is why Vela’s move to Chrome’s own network stack matters more to its connections than any reordering of extensions could.
Vela’s developers treat this fingerprint as a real risk, having moved the app’s own requests in September 2026 to Cronet, Chrome’s network stack, so that “at the connection level they look like Chrome rather than like an Android app’s HTTP library”. The hidden WebView is a separate case, because Android’s WebView adds X-Requested-With: app.vela to its requests, a header their code records as “NOT fixable by an app”. Vela’s privacy page of 8 October 2026 says the app now carries those pages’ requests over its own network stack instead, which leaves the header off. A hidden-page request that Vela cannot carry that way still names the app that sent it, which narrows the anonymity set from everyone at an address to the users of one app.
A site can fingerprint a browser from the way it draws, but on a phone that fingerprint alone singles out only a minority of devices, so it identifies a phone mainly in combination with other signals. This is the consortium’s active fingerprinting, where “a site runs JavaScript or other code on the local client”. Mowery and Shacham showed it in 2012: “Render text and WebGL scenes to a <canvas> element, then examine the pixels produced.” Different systems draw the same text as different pixels, since the font rendering and the graphics processing unit (GPU) each affect the output, and a script reads the pixels back and hashes them in eight lines:
const c = document.createElement("canvas");
const ctx = c.getContext("2d");
ctx.font = "16px Arial";
ctx.fillText("Levels of privacy", 2, 20);
const png = new TextEncoder().encode(c.toDataURL()); // the drawing, encoded as a PNG string
const digest = await crypto.subtle.digest("SHA-256", png);
const fingerprint = [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, "0")).join(""); // 64 hex characters to send
In 2010 Eckersley found 83.6% of 470,161 browsers unique. In 2018 Gómez-Boix and colleagues measured 2,067,942 fingerprints on a large French website, of which 33.6% were unique, against only 18.5% of the fingerprints from mobile devices, as Laperdrix and colleagues’ survey reports. Each fingerprint in the 2018 study took in every attribute the researchers measured, so on a phone the canvas alone can make no more than 18.5% of fingerprints unique. That is one site’s audience, and no study I found measures fingerprint uniqueness on GrapheneOS. Vela’s privacy page names the same risk, stating that Google’s script in its hidden WebView “could set cookies or fingerprint the browser”. The browser on a phone therefore adds one signal for Google to combine with the IP address and the history.
A phone’s fingerprint shrinks its anonymity set even when the fingerprint is not unique, which leaves the IP address only a few phones to tell apart. Each bit of identifying information halves the possibilities, so the 7.93 bits of a phone’s canvas in the 2018 study narrow the possibilities to about one in 244 on average. Eckersley found that 15 to 20 bits nearly always identify a browser “given its IP address”. Behind an address a thousand users share, the canvas alone leaves about four phones. Luo and colleagues saw a commercial service re-identify Brave and canvas-noise extensions from a stable IP address until the address left its /24, on desktop Chrome rather than phones. While bits add only for independent signals, a phone whose fingerprint is not unique can still be singled out once the service adds the IP address it sees, making the network layer as important as the device.
Privacy has to hold at every layer at once, because the account, the app, the device, the network as the service and the path see it, and behaviour can each identify the user. The weakest of these layers decides the level. The level also depends on the order in which the user protects the layers, and the third section follows the same sequence. The table below sets each layer beside what can identify the user there, whether that needs code on the phone (active) or only the request (passive), what it looks like in the two apps this post examines, and where the answer comes in the third section.
| Layer | What can identify the user | Passive or active | In NewPipe and Vela Maps | Answered in section 3 by |
|---|---|---|---|---|
| Account | a Google Account, signed in once | passive | neither app has one | a user profile of its own; never signing in there |
| App | identifiers the app or the service issues (a session cookie, visitor data); the app named in a header | passive | Vela’s Google session cookie and the X-Requested-With: app.vela header; NewPipe’s visitor data | short sessions; front-ends that send shared values |
| Device and browser | ANDROID_ID, the advertising ID, global settings, a canvas fingerprint | passive and active | Vela’s hidden WebView runs Google’s script; NewPipe runs none | user profiles; no sandboxed Google Play |
| Network, seen by the service | the IP address; the TLS ClientHello | passive | both apps show their IP address; Vela connects through Chrome’s stack | a VPN or Tor per profile |
| Network, seen on the path | the Server Name Indication (SNI) and traffic patterns | passive | both apps | a VPN; multihop and Defense against AI-guided Traffic Analysis (DAITA), both in section 3 |
| Behaviour | histories, trips, subscription lists, and the order they happen in | passive | Vela’s trips; NewPipe’s imported list | the user, and the order of operations |
Vela Maps and NewPipe#
Vela Maps, which I run on GrapheneOS, uses no Google Account or Google Play services, and its offline regions keep searches on the phone. Its place lookups still reach Google, though, and each one carries the IP address. Vela’s README calls the app degoogled, and the claim holds on the phone, since there is no account, no Vela backend and, as its privacy page adds, no telemetry. The app draws the map from open vector tiles and open place data, which the README calls Vela data. However, the same README’s table shows a search and a place lookup reaching Google, and directions sending it “the traffic, and only the traffic”, since the route itself is computed by an open routing server or on the phone from a downloaded region. Vela’s privacy page lists what a search sends: the IP address, the query text, the map viewport, and a cookie that “lives only while Vela runs”. For reviews, photos, popular times, transit directions and departure boards, Vela also loads Google Maps in a hidden, signed-out WebView, where, as the first section showed, Google’s JavaScript can set cookies or fingerprint the browser. Vela therefore sends no account and no Google Play services identifier, but every place lookup that reaches Google still carries the IP address, the query and the location.
Can Google still work out who you are from the places you look up? It can in principle. Directions requests send it the “origin + destination coordinates” of each trip, and a pair of places such as home and work can be enough to single out one person. Golle and Partridge found that for home and work locations at the level of a census block, the median anonymity set of an American worker is 1; de Montjoye and colleagues found that four spatio-temporal points uniquely identified 95% of about 1.5 million users of one mobile operator. The trips themselves act as a pseudonym, since anyone holding the requests can correlate a journey from A to B, even one from a new IP address, with every earlier journey between the same two points. However, Wang and colleagues report that the methods before theirs for matching real trajectories reached a maximum hit-precision of only about 20%, although their own did better. I found no report of Google matching Vela’s requests against a location history. While both limits stand, a Vela user who repeats the same trips from a new IP address can still be singled out by the trips alone.
NewPipe does for YouTube what Vela does for maps, using no Google Account or Google Play services and keeping subscriptions on the phone. To keep working, though, it sends YouTube visitor data, a per-visitor value that the service issues, and for three months of 2025 it also ran BotGuard, YouTube’s own code. Its README says the app parses the website, or uses an internal application programming interface (API), when the official one is restricted. By February 2025 that was no longer enough, because YouTube, as NewPipe’s developers wrote, now required integrity checks, and passing them meant running BotGuard, “an obfuscated virtual machine implemented in JavaScript that performs the integrity checks and gives us an integrity token.” Only version 0.27.6 ran Google’s code on the phone, the first section’s active case, since 0.27.7, released in May 2025, stopped. Version 0.29.1 (15 August 2026) presents itself instead as YouTube’s Android or Apple Vision Pro app. NewPipe’s extractor library still takes visitor data from YouTube, because a random one no longer returns valid responses, and fetches it fresh for every player request, so the app keeps it for one request and never on disk. NewPipe’s improvement is real, but its requests carry YouTube’s visitor data and client names and an IP address, which Privacy Guides notes stays visible to the video providers.
NewPipe builds its requests so that every install sends the same values, which leaves the IP address, the visitor data YouTube issues and the channels the app fetches to tell its users apart. The extractor’s request builder shows what goes in the body of every request to YouTube’s internal API, abridged here to the fields that carry a value:
final JsonBuilder<JsonObject> builder = JsonObject.builder()
.object("context")
.object("client")
.value("clientName", innertubeClientRequestInfo.clientInfo.clientName)
.value("clientVersion", innertubeClientRequestInfo.clientInfo.clientVersion);
// ...
if (innertubeClientRequestInfo.clientInfo.visitorData != null) {
builder.value("visitorData", innertubeClientRequestInfo.clientInfo.visitorData);
}
// ...
builder.value("hl", localization.getLocalizationCode())
.value("gl", contentCountry.getCountryCode())
.value("utcOffsetMinutes", 0)
.end();
The client name and version are constants, so every install claims to be the same YouTube Android app, version 21.03.36 on Android 16, or the same app on an Apple Vision Pro, “RealityDevice14,1”. The language and country are the app’s own settings. The offset from Coordinated Universal Time (UTC) is always 0, so the phone’s time zone is not in the body. The app fetches the one value YouTube issued, the visitor data, again for every request. Language and country do narrow the set, since a rare pair of them is shared by fewer users. The first section’s ClientHello still travels with every connection, outside the body. Within those limits the body of a NewPipe request hides its user well, and what remains to tell users apart sits around it: the IP address, the visitor data, and the subscription list the user brings from the old account.
An imported subscription list can identify a NewPipe user, because YouTube can link the same channels to the signed-in account behind the export, even from a new IP address. NewPipe’s instructions for this begin “Import YouTube subscriptions from Google takeout”, and the app’s feed then fetches each channel. Its own code shows the developers see the fetch pattern as a fingerprinting risk, and the code randomises the order “to attempt to resist fingerprinting”, fetches three channels at a time and pauses for a random six to twelve seconds after every 50 channels. Randomising changes the order and leaves the set as it was. No study I found covers YouTube subscriptions, but a subscription list is a set of interests. A 2021 study of 1.5 billion Facebook users found that a user’s four rarest interests make them unique with 90% probability. If channels work like those interests, a list’s four rarest channels could make its owner unique. Large language models (LLMs) have also made linking accounts across platforms far more effective. Lermen and colleagues report up to 68% recall at 90% precision, against near 0% without an LLM. These are capabilities shown on research datasets, not evidence of what YouTube does. Still, the same set fetched from a new IP address can act as an identifier the user brings from the old account.
Both apps describe what they give as anonymous. NewPipe “aims to provide a private, anonymous experience”, and Vela says its “Place lookups go out anonymously”. In its strongest form the claim holds some truth. Vela’s own settings screen states the case in full: “Vela talks to Google’s public endpoints straight from this device: no backend, no account, no API key. Google sees your IP, query and map area, not who you are.” Its privacy page adds that there is “No device id or account id from Vela”, and that a search carries a cookie that “exists only in memory and starts over every time Vela starts”. On this view nothing in a request identifies the user, the search cookie ends with the session, and a VPN exit IP is shared by many people. Mullvad itself says that it usually assigns lots of users to every exit IP. If the only question were whether the requests alone let Google link them to a Google Account, the apps would be right.
What the apps give is pseudonymity, not anonymity. An IP address, a session cookie or visitor data can single out the user even when a request carries no account. The first section drew that distinction from Pfitzmann and Hansen, and it matters because Vela’s claim is about linking while the risk is correlation. Vela’s own code says as much of the second cookie, the one a place lookup carries: “A saved Google cookie is a pseudonymous ID: everything an install asks for while it lasts can be linked into one history.” Vela’s “linked” there is correlation, because the result is one history with no account attached. Vela keeps that cookie on disk, and how long it lasts is a setting:
private fun periodMs(m: String): Long = when (m) {
LAUNCH -> 0L
DAY -> 24L * 3600_000
else -> 7L * 24 * 3600_000
}
The default is the week, and my phone’s settings screen (canary build, 26 September 2026) says what that means: “Google remembers this phone by a cookie, so what Vela looks up while it lasts can be linked together, without any name or account.” A cookie that ends with the session only stops anyone from using that cookie to correlate one session with the next, and does nothing about the identifiers that outlast it: the IP address a signed-in app shares, the same trips from A to B, and the same subscription list fetched again. So the pseudonym is whichever identifier outlasts the session, and Vela’s setting decides the life of one such identifier.
A new Google session in Vela, or fresh visitor data in NewPipe, starts a new identifier without starting a new history. Vela’s code rotates the session only when Android starts its process, and Android keeps a cached process until it needs memory, so a weekly session lasts at least a week. The new cookie arrives from the same IP address, and Eckersley noted that once a user deletes cookies on a used address, the site “could, with high probability, link their new cookie to the old one”. NewPipe’s extractor fetches fresh visitor data for each of a video’s three player requests, which leave one address within seconds, so YouTube could correlate them by address and timing. Each visitor data value lasts seconds, but NewPipe keeps the cookies of a solved reCAPTCHA, VISITOR_INFO1_LIVE among them, and sends them with every request until the user taps Clear reCAPTCHA cookies. Each rotation therefore shortens the history one identifier carries, and only a new IP address at the same moment separates the two sessions.
Once correlation builds a history from those identifiers, one sign-in within the same user profile, or a signed-in app sharing the address, can link the whole history to an account. In Brown v. Google, the class action over Chrome’s Incognito mode, the court’s 2023 order records the plaintiffs’ expert as saying that, aggregated, Incognito browsing data lets Google “uniquely identify a user with a high probability of success.” That aggregated data is the history the first section described, and a sign-in adds the one thing it lacks, an account with a name. That is the plaintiffs’ evidence, not a finding about NewPipe or Vela, and nothing I read shows Google doing this with either app’s traffic. The apps still give a real level of privacy, which is pseudonymity, and how close it comes to anonymity depends on the identifiers the user carries between sessions.
Correlation can join Vela’s and NewPipe’s requests into one history without an account, through the exit IP address they share, the timing of their requests, and what they fetch. Figure 1 follows them through the recommended setup, one GrapheneOS profile behind one VPN, Vela on its weekly session. Opening a place carries the exit IP and the saved Google cookie, under which, Vela’s privacy page concedes, Google can link the places opened “into one history with no name attached”. When NewPipe opens a video from that exit IP minutes later, timing narrows the address’s many users to the few active then, an inference no source confirms. After a rotation, repeated trips and channels can carry the history across. Luo and colleagues found, on desktop browsers, that a kept cookie held one visitor identifier through a new browser and IP address, the risk NewPipe’s stored reCAPTCHA cookies carry. While no source I read shows Google joining YouTube and Maps logs, one sign-in on that address would link that history to an account. The setup removes the account from every request yet leaves Google enough to keep one history per address, which is why the third section ends on the user’s order of operations.
Overcoming the Privacy Issues#
Any fix has to keep the apps as usable as the default ones, or close to it. Where privacy comes from sharing an address, the cost falls on usability. How much of that cost to bear depends on the user’s threat model. For example, keeping out of an advertising profile asks for much less than staying unlinkable to someone who can make a company hand over its logs. Sharing an IP address with many other people hides the network layer, and it is also what can trigger Google’s unusual traffic message and YouTube’s temporary IP bans. Google’s help page on that message says: “You could get this message if others that use the same Virtual Private Network (VPN) you use are sending automated searches to Google.” NewPipe’s list of frequently asked questions (FAQ) warns that YouTube may temporarily ban an IP address, and that the problem can also occur behind a VPN. (delete the sentence) The more people share the address, the more likely it is that one of them sends automated traffic, and the more likely a user is to meet challenges and failed videos. Thus, what a measure costs in daily use counts alongside what it separates, since a setup that makes the apps unusable is unlikely to last.
Every layer has at least one mitigation, but no single party provides them all: the apps cover the app layer, the operating system covers the device, the VPN provider the address, and behaviour rests with the user. The table below sets the first section’s six layers against what exists today, who provides it, what the user must still do, and where it stops.
| Layer | Mitigation in the app | Mitigation in the operating system or network | Left to the user | Limit |
|---|---|---|---|---|
| Account | neither app has one | a user profile of its own | never sign in there | one sign-in can link the whole history |
| App | Vela: a Google session that restarts every week, day or launch, “Use Vela without Google”, “Block Google’s page telemetry” (off by default) and a counter of requests to Google. NewPipe: visitor data fetched fresh per request; a shuffled feed | for the app.vela header, none: Vela’s code calls it “NOT fixable by an app” | set the session to every launch; start subscriptions fresh | the header on hidden-page requests Vela cannot carry over its own stack; a new session loses reviews and popular times for a while |
| Device and browser | Vela gives its hidden WebView a desktop identity and opens it only for reviews, photos, popular times, transit directions and departure boards; NewPipe no longer opens one | user profiles (a different ANDROID_ID in each); no sandboxed Google Play, so no advertising ID | use Vela without Google when reviews and photos are not needed | the time zone, the network country and the SIM’s country and operator are visible in every profile |
| Network, seen by the service | Vela: Cronet, so connections look like Chrome’s. NewPipe: OkHttp with YouTube’s own user agents | a VPN or Tor per profile; “Block connections without VPN” | turn the VPN on before the first launch | exit IP fingerprinting on 32 of 541 Mullvad servers on 22 September; shared addresses trigger “unusual traffic” |
| Network, seen on the path | nothing | a VPN hides the server name from the carrier; multihop and DAITA | choose a DAITA server | DAITA on select servers only; Tor VPN is beta and “may leak information” |
| Behaviour | Vela’s offline regions; “Use Vela without Google” | ending a profile’s session | the order of operations | retention: 9 months for part of the IP address, 18 for cookie information |
The table shows that no protection in the behaviour row works unless the user chooses it. Every entry in the last column is a place where one layer’s protection stops short of the next, so the fixes in the rest of this section follow a fixed order.
The operating system decides what the front-ends share with the signed-in apps, and on GrapheneOS user profiles keep them apart. GrapheneOS describes Android’s user profiles as “isolated workspaces with their own instances of apps, app data and profile data.” Its FAQ is direct: “Profiles should be used when separate identities are desired.” This is how I run NewPipe and Vela Maps, in a profile of their own. The separation also covers two device identifiers from the first section. ANDROID_ID is unique to each combination of profile and app signing key, so the same app shows a different value in each profile. GrapheneOS ships without Google’s apps and services, and the user installs sandboxed Google Play only in a chosen profile, so the private profile can run with no sandboxed Google Play at all, and therefore with no advertising ID. GrapheneOS also lets the user end a secondary profile’s session so that none of its apps can run beside the front-ends (the Owner profile needs a reboot for that), and adds a Network permission toggle that can keep any app off the network. Within the limits the next paragraph sets out, profiles give NewPipe and Vela Maps a separate identity in the operating system.
User profiles do not hide the phone’s country, because Android reads the SIM’s and the network’s country codes from settings that every profile shares. In Android’s TelephonyManager, getSimCountryIso() and getSimOperator() read system properties with no permission or profile check, and the telephony service sends each change of network country to every user. The code shows that every profile shares these values, and GrapheneOS’s FAQ confirms this for the network country code by listing it among “the global OS configuration available to apps”. Issue 502 asks GrapheneOS for standard country values and is open and marked high priority, and I offered to implement it in June 2024. However, GrapheneOS’s own account on its forum calls the feature planned but not yet available. While profiles give each app its own ANDROID_ID and keep sandboxed Google Play out, the private profile still tells every app the SIM’s country and the network the phone is on, until GrapheneOS ships what issue 502 asks for.
Airplane mode clears the network’s country code but leaves the SIM’s, so hiding both identifiers needs the radio off and no SIM in the phone. According to GrapheneOS’s FAQ, airplane mode fully disables the cellular radio and still lets the user turn Wi-Fi back on. With the radio off, Android’s LocaleTracker clears the network country but keeps the last known one and sends it to apps listening then. This leaves the SIM’s values, which Android clears only when the SIM’s records are removed. A user’s tests on the GrapheneOS forum found the country still detected on a phone with a SIM in airplane mode and not detected once the SIM had been removed, which matches the code. No test I found covers disabling the SIM in Settings instead. While airplane mode is, in GrapheneOS’s words, “the only way to avoid the cellular network tracking your device”, hiding both codes costs calls, texts and mobile data whenever the apps run, which suits a separate device better than the user’s everyday phone.
Several GrapheneOS defaults and settings hide identifiers at the local network and device layers at little cost to how NewPipe and Vela work. On Wi-Fi, GrapheneOS gives the phone a new random media access control address for each connection by default, and its Dynamic Host Configuration Protocol client sends no hostname, so the phone carries no fixed hardware address or hostname between connections. On the device, the Sensors permission gives a denied app zeroed readings, costing only apps that need a compass. Storage Scopes and Contact Scopes hide other apps’ files and the contact account’s name, and deleting a profile made for one need also deletes its ANDROID_ID. Android adds a time zone set by hand, which shifts every clock on the phone, and, since Android 13, a language for each app. Although none of these hides the device model or that the phone runs GrapheneOS, which the FAQ says apps can determine, the defaults keep the phone’s own hardware address and hostname off Wi-Fi and the settings narrow what the device layer tells apps in the private profile.
Those profiles also have their own VPN configuration, so the front-ends can reach the internet from a different IP address than the signed-in apps, through a VPN or through Tor. Neither helps with traffic that goes around the tunnel, or once the user signs in. Android lets each user or work profile run a different VPN app, and Android’s “Block connections without VPN” switch is, in GrapheneOS’s words, “needed to prevent leaks” when the VPN app’s service isn’t running. I use Mullvad in the NewPipe and Vela profile. However, even with Mullvad the exit IP carried a risk, because, as Mullvad disclosed in May 2026, switching servers could let websites “confidently guess” that the same user had connected from both servers. On 22 September 2026 Mullvad reported its fix on 509 of its 541 online servers, so 32 still carried the risk that day. For Tor, the Tor Project states the limit plainly: “Tor only protects applications that are properly configured to send their Internet traffic through Tor.” Signing in over Tor, the Tor Project warns, leaves a site not knowing the user’s location “but they know who you are”, so any account the user signs in to identifies them through the tunnel.
Other privacy technologies add protection on the network layer, mostly against observers along the path, and leave every other layer of identifiers where it was. (delete the sentence) Mullvad’s multihop routes the connection through two or more servers in separate jurisdictions, which makes it harder to correlate the traffic entering the VPN with the traffic at its exit. Mullvad’s DAITA makes every packet the same size and adds cover traffic. DAITA works against an observer at the internet provider who reads patterns rather than content, but Mullvad offers it only on select servers in Amsterdam, London, Los Angeles and New York. The Tor Project’s Tor VPN routes chosen apps on Android through Tor. However, it is beta software that “may leak information”, and its threat model states the limit this post has argued: “Tor VPN does not magically make all apps anonymous or pseudonymous.” Each of these works on the network, so the account, the app’s own identifiers, the device and the user’s habits stay with the profile and with the user.
The last layer is behaviour, because no profile or VPN can separate identities that the user links by importing the same subscription list or repeating the same trips. Mullvad’s guide to blogging anonymously warns that if one computer serves both identities, “you run a high risk of mixing up your identities and therefore creating a link between the two.” On a phone with two profiles the same holds. Importing the Google Takeout list into NewPipe brings the old account’s channels into the new profile, and searching the same routes in Vela brings the same trips. Vela’s offline regions help here, because in a downloaded region the map, search and routing work with no network, so those lookups never reach Google. One sign-in to a Google app inside the private profile can link the profile’s history to the account at once. Separate identities, in GrapheneOS’s phrase, stay separate only while the user keeps the two profiles apart.
No protection covers an identifier the phone sent before it was in place, which is why the order of operations decides whether any of them holds. For example, a VPN hides the addresses of later requests, a new Vela session cuts later place lookups from the earlier ones, and a profile isolates only the apps installed once it exists. What Google already holds can be correlated with later requests for as long as Google keeps it, and the first section gave the figures: 9 months for part of the IP address in advertising logs, 18 for cookie information. Vela’s page says the same of its cookie, that “While one of those sessions lasts, Google can link the lookups made under it”, which is why its setting caps the session. None of this is a measured case, since no source I read shows Google correlating a user’s earlier requests with later ones. The logic of the sources is enough for the setup, because each step has to be in place before the one that depends on it, and the list below keeps that order.
Conclusion#
NewPipe and Vela Maps do provide major improvements, since both use no Google Account or Google Play services, NewPipe keeps subscriptions on the phone, and Vela can work with no network at all. However, there are levels of privacy, and what they give is pseudonymity rather than anonymity. Identifiers remain, from the IP address a signed-in app shares and the connection that identifies the app, to the trips a user repeats and the subscription list they import. They give anyone who holds them ways to correlate and determine with a high degree of confidence that it is the same person behind an earlier session or a signed-in account. The research shows that capability, and no source I found shows it in Google’s practice. In the end the operating system, a VPN or Tor, and the user’s own order of operations decide how much of that capability remains. Beyond these two apps one question applies to every privacy preserving application, Signal, Tor Browser and Aurora Store included: what does it still send, and what could anyone correlate from that traffic?
A setup to follow, in order, built from the sections above:
- Run GrapheneOS and put NewPipe and Vela Maps in a user profile of their own, with no sandboxed Google Play in it, so they share no account or advertising ID with the signed-in apps.
- Keep every signed-in Google app in a secondary profile rather than the Owner, and end its session while you use the private one.
- Give the private profile its own VPN (Mullvad, in my case) with “Block connections without VPN” turned on, before either app runs there for the first time, and treat Tor VPN as a test while it is in beta.
- Start NewPipe’s subscriptions fresh instead of importing a Google Takeout list, so the new profile does not begin with the old account’s channels, and clear NewPipe’s reCAPTCHA cookies after solving one.
- Download Vela regions and search offline where you can, so those lookups never reach Google.
- In Vela, set Settings > Privacy > Google session to start a new one every time Vela opens, or turn on Use Vela without Google, so that place lookups cannot build a week of history. Vela starts that new session only when Android starts its process, so tap Start a new session now to end one at once.
- Never sign in to a Google Account inside the private profile, since one sign-in can link its whole history to the account.