Legal

Privacy policy

Written to be true rather than reassuring. Where something is uncomfortable it is stated here rather than left out.

Last updated 5 September 2026

This policy has not been reviewed by a lawyer. It is an accurate description of the system written by the people who built it, published so that it is checkable. It will be reviewed before it is relied on as a legal instrument, and this notice will come off when it has been.

Digital Services LLC operates ForestVPN. This policy covers the ForestVPN apps for iPhone, iPad, Mac and Apple TV, the servers that carry your traffic, and this website.

Our commitment

ForestVPN does not sell, use, or disclose to any third party the data described in this policy, for any purpose, other than as strictly necessary to operate the service — that is, Apple for payment, and the infrastructure providers listed below, each acting solely as a processor on our instructions and under contract. We do not run advertising, we do not profile you, and we do not share anything with data brokers, analytics vendors or attribution networks. There are none in the app.

The app contains no analytics SDK, no attribution SDK and no advertising identifier. Its privacy manifest declares no tracking and no tracking domains, and the only two data types it declares — a device identifier and purchase history — are both marked as not linked to your identity and used only for app functionality.

What we never have

  • Your browsing. There is no field anywhere in our systems for the sites you visit, the names you look up, or the addresses you connect to. Not a short retention period — no such column exists.
  • Your identity. There is no email address, no password, no phone number and no name. An account, if you create one, is a 128-bit random number. The accounts table has no contact field of any kind.
  • Your card. Payment happens at Apple, or — if you buy on the web — at the processor you choose: Stripe, CloudPayments or NOWPayments. Apple gives us a signed receipt and a device-derived token; a web purchase gives us a one-time reference number we generate ourselves, never your card. Either way we never see a card number, and for a crypto payment the processor is the only party that sees anything at all. See paying by card or crypto.

What lives on your device

A machine key

On first launch the app generates a key pair that stays on the device, in the system keychain, marked so that it never syncs to your other devices or to iCloud. It is not an advertising identifier and it is not shared with anyone. We store a hash of its public half, which is how a device is recognised across launches.

It is permanent. It is never rotated, and it survives deleting the app. Reinstalling does not give you a new identity — the reinstalled app presents the same key and is recognised as the same device. This is deliberate: it is what stops one device claiming an unlimited number of free allowances. It also means uninstalling is not a reset, and you should know that before you install.

A session key

Every connection generates a fresh key that exists only in memory and is discarded when you disconnect. It is never written to disk and never reused, so an exit server sees a key it will never see again.

Accounts, subscriptions and allowances

One service issues connection credentials and keeps the records a subscription needs. It holds:

RecordWhat it containsKept
Device

A hash of your device’s public key, its platform, when it was first seen and the last day it was seen, and the account it is attached to if you attached one.

indefinitely

Account

A random 128-bit number and the dates it was created or suspended. No email, no password, no name.

indefinitely

Subscription

Apple’s subscription identifier, the tier, what it is paid until, and trial state.

indefinitely

Billing events

Apple’s signed transaction notifications, stored as Apple sends them, so a payment dispute can be settled.

indefinitely

Daily usage

Bytes and connection count per device per day, to apply the free tier’s limits.

31 days

Monthly usage

Total bytes and connections per device per month.

indefinitely

Decision ledger

An append-only record of allowance decisions — which device asked, what was decided and why — so a disputed refusal can be explained months later.

indefinitely

Support code

A short code you generate in the app, bound to your device, so that an email from you can be matched to a device record.

72 hours

Ticket binding

A hash of your device’s key next to a hash of the session identifier the connect service will use, the tier, and how many of the ticket’s bytes have been used. This is the one row in this database with a device on one side and a session on the other.

settlement + 1 hour, or up to about 17 days if the ticket is never redeemed

The ticket binding row above is the one exception, and it is stated here rather than left off the table: while it exists it names both your device and the session it belongs to, which is what lets a settled session be charged against your allowance and a revoked device be cut off mid-session. It is deleted automatically, not by request — an hour after the session it names settles, or when the ticket itself expires unused, whichever comes first. None of these records, including that one, contains an exit server, the address you connected from, or anywhere you went: the issuing service never learns any of those. They exist only at the separate service described in [what happens when you connect](#session), which has no way to look up who you are.

The credential itself

To connect, your device asks this service for a ticket. The ticket is blind-signed: the signature is produced over a value we never see, so the ticket you present at connect time cannot be recognised as the one issued to you. It carries exactly two facts — which tier signed it and which fortnight’s key was used — and nothing else. The issuing service never learns a location, an exit, a session, or whether a tunnel ever came up.

Paying by card or crypto

Apple bills every subscription bought in the app, and we never see a card number: Apple sends us a signed receipt and a device-derived token. A subscription can also be bought on the web, through a card processor — Stripe or CloudPayments — or a crypto processor, NOWPayments, and that path is different enough to describe on its own.

When you check out on the web, we mint a one-time reference number ourselves and hand that to the processor — never your account number. Under this policy the account number is a credential; putting it in a payment processor's dashboard, webhook payloads or support tooling would be publishing a password. The reference expires within the hour and, held on its own, opens nothing.

What we keep from a web purchase: which processor billed it, that processor's own subscription id, the tier, the date it is paid until, and whether it has been cancelled or revoked. What we never receive and never store: your name, your email, your billing address, your card fingerprint, or — for a crypto payment — anything about you at all. The code that writes a payment row has no field that could hold any of those; adding one would be a visible, reviewed change to a file everyone building a payment rail has to touch, not something a bug could do quietly.

Stated as plainly as we can: a records request served on us produces a tier and a paid-until date. The same request served on the payment processor produces a person and a card. That is deliberate. It is the trade of paying on the web instead of through Apple, and it is also why we would rather this data sit with a company built to hold it than sit with us as well.

Cancelling an Apple subscription happens in Settings → Apple ID → Subscriptions. A card subscription is cancelled through the processor's own customer portal, which authenticates you by the email it holds — not by us, since we hold none. A crypto payment buys a fixed term and simply expires; there is nothing to cancel.

If you lose your account number after a web purchase, support can ask the processor to refund you, but cannot restore access — there is no email or password on our side to prove the purchase was yours. A crypto payment cannot be refunded at all. We would rather you read both of those sentences before paying than after.

What happens when you connect

A separate service accepts the ticket and opens the session. It sees the address you are connecting from, the location you chose and your one-time session key, and it holds a session record containing the tier, the epoch, that session key, the exit, your tunnel addresses, an expiry and a byte budget. The record deletes itself when the session expires. Your source address is never written into it.

This service has no database binding at all. It has no handle by which an account or a device could be reached, so a bug on the connect path cannot write your identity into a session record — there is nothing to write it with. A build job named the privacy seam holds fails the build if that binding is ever added. This is the one privacy property here that does not depend on us behaving well.

Exit servers

Exit servers boot from memory. There is no disk to write to, state is wiped on every reboot, and there are no logging code paths in the software that runs them.

While a session is up, an exit necessarily handles the address you connect from — it terminates the tunnel — along with a session key it will never see again and the traffic itself. It does not record any of it. What it reports back is aggregate, delayed and rounded: bytes per peer per period, never per connection or per destination.

To keep the servers hosted, an exit may rate-limit or refuse abusive traffic patterns locally, using only what is in memory on that server and keyed on the network the traffic came from, never on a subscriber. There is no record of abuse that outlives a session, because keeping one would mean resolving a session to a person.

Analytics

We keep operational counters: how many credentials were issued and refused, connection outcomes and timings, byte totals, and per-server aggregates. They are written to an analytics store that nothing in the request path reads back.

Two things about it should be said plainly.

  • The rows about credential issuance and settlement carry a pseudonymous per-device tag — a keyed hash of your device key hash, not the hash itself — along with a country code and a network operator number. That is personal data under the GDPR, not anonymous data.
  • Retention is 90 days and cannot be changed, and there is no deletion API. We cannot delete an individual’s analytics rows on request; we can only wait for them to expire. Rotating the key that makes the tag orphans future rows from past ones; it does not remove the past ones, and it does not retract a correlation made while the old key was in use.

No row carries a subject and an exit server together. The datasets that carry a device tag do not carry a server, and the datasets that carry a server do not carry a subject.

This website runs no analytics at all. It sets no cookies, loads no third-party scripts, embeds nothing, and self-hosts its fonts.

Who else processes it

Each of these acts on our instructions, under contract, and is bound to protect the data to at least the standard set out here.

Cloudflare
Hosts the control services, their databases and this website, and terminates TLS for our domains. Because TLS terminates there, Cloudflare is in a position to see the metadata of requests to our hostnames regardless of what our own code records. This is a real limit and we would rather state it than imply it away.
Apple
Sells and bills every subscription bought in the app, and tells us that a subscription exists. Apple has its own privacy policy and its own relationship with you. We receive a signed receipt and a device-derived token, never a card number, name or email.
Stripe
Processes card payments for subscriptions bought on the web, and runs the customer portal where a card subscription is managed and cancelled. Stripe holds the buyer's name, email, billing address and card details — none of it reaches us.
CloudPayments
An alternative card processor for web purchases, offered where it serves buyers better than Stripe. Same boundary: it holds the payment identity, we hold a subscription row with no name attached to it.
NOWPayments
Processes cryptocurrency payments for web purchases. It is the payment method where even the processor holds the least about you — no card, no bank account — and, unlike the others, a crypto payment cannot be refunded. See paying by card or crypto.
Server providers
The companies that host our exit servers. They can see traffic volume at their own network edge, as any host can. They have no access to the servers’ memory or to your traffic.

Retention

Retention is listed per record in the table above. In summary: session records last only as long as the session; ticket bindings — the one record with a device and a session on the same row — are deleted an hour after settlement or at the ticket's own expiry, never more than about 17 days out; support codes last 72 hours; daily usage rolls off after 31 days; analytics expire at 90 days and cannot be deleted early; device rows, account rows, subscription and billing records, monthly byte totals and the decision ledger are kept indefinitely, because a subscription dispute or a refused allowance has to be explainable later. This is retention for what we hold — a web purchase's receipt, dispute correspondence and card record live at the processor and follow its own retention policy, not this one.

Deletion, and what a request can actually reach

Email support@fvpn.net with a support code from the app (Account → Get help). The code is the only way we can tell which device record is yours: we have no email address, username or account name to authenticate you by. Without it we cannot act on a request about a specific device.

Being exact about what that request reaches today:

  • Daily usage rows can be removed, and expire after 31 days anyway.
  • Unlinking one device while leaving the account itself in place cannot be done as routine work. The app warns you before you create the link, and there is no self-service route that only severs it — the sole way is the account deletion below, which severs it for every device on the account by removing the account itself.
  • In-app account deletion is available: Account → Delete account. It is permanent — it removes the account, reverts every device linked to it back to anonymous (each keeps whatever it separately bought), and cannot cancel account-owned subscriptions, which Apple keeps billing until you cancel them yourself in Settings. It asks for the account's full number rather than trusting that you are signed in on a device, because every device on an account shares that authority equally and one of them should not be able to destroy it on the others' behalf. It only deletes an account: a device with no account attached has nothing here to delete.
  • Analytics rows cannot be deleted at all and expire at 90 days.
  • Monthly byte totals, billing records and the decision ledger are kept. The ledger is append-only on purpose: a record that can be quietly edited cannot settle a dispute.

You can stop all collection at any time by deleting the app and not connecting. Note that this does not remove the records above, and that the machine key survives deletion — see what lives on your device.

If you are in the EU, the UK or California, you have rights of access, correction, deletion and portability over personal data we hold about you. A device key hash is pseudonymous personal data, not anonymous data, and we treat it as such. Where we cannot satisfy a request — the cases above — we will say which one applies and why, rather than claiming we cannot identify you.

What this does not protect against

One record links your device to a session, and through the device to your account if you have linked one. It is the ticket binding set out in accounts and subscriptions: it exists so the allowance can be metered and a revoked device cut off mid-session, and it is deleted an hour after that session settles. Nothing anywhere links either of them to an exit. We say it that way rather than claiming a separation we do not have — and these are the other limits, for the same reason:

  • The service that issues credentials and the exit that carries your traffic each see your session key at different moments. Parties who were compelled together, or who colluded, could use that to rejoin a session end to end. We keep no record that would do it, and no single one of them can do it alone.
  • If you use the devices page to send a router to a different exit, the location you chose is stored against that device — and so, if the device is linked to an account, against your account — until you choose another. It is what you asked for, never what we observed: the device's acknowledgement is a number echoed back, not a place.
  • TLS for our domains terminates at Cloudflare, so metadata about requests to our hostnames exists there regardless of our own code.
  • Your device key hash is stable, and pseudonymous analytics rows keyed to it live for 90 days.
  • The set of people you are indistinguishable from is everyone holding a ticket signed by the same tier key in the same fortnight — not “all our users”. At launch that set is small. We would rather say so than describe an anonymity we do not have yet.

A VPN moves who can see your traffic. It does not make you anonymous, and this one does not claim to.

Children, changes and contact

The service is not directed at children under 13, and we do not knowingly collect data from them. We have no way to know a user’s age, because we collect nothing that would tell us.

If this policy changes materially we will change the date at the top and describe what changed. Because there is no email address on file, we cannot notify you by mail; the app shows a notice instead.

Questions, requests or complaints: support@fvpn.net. The controller is Digital Services LLC.