Curl Flow

Privacy

Last updated 27 September 2026

This page covers curlflow.eu — the front page there, and the Curl Flow application at curlflow.eu/app. It is specific to this product: Siin App OÜ runs other things, and they have their own policies.

Curl Flow runs almost entirely inside your browser. That is not a privacy posture we adopted afterwards — it is how the thing is built, and it is why this page is short.

Who is responsible

Curl Flow is run by Siin App OÜ, registry code 17236273, Sõle tn 82-14, 10314 Tallinn, Harju maakond, Estonia. We are the data controller.

For anything on this page — a question, a request, a complaint, a deletion: support@curlflow.eu.

What never leaves your browser

Worth stating first, because it is most of the answer:

  • Audio files you drop in. They are decoded by your browser and analysed on your own machine. They are never uploaded. We never receive the file, the filename, or anything derived from it beyond a single flag recording that the audio was your own rather than our demo track.
  • Microphone input. If you choose live input, the audio is analysed frame by frame in your browser and discarded. It is not transmitted, ever — and it is not recorded unless you press Record Take, which writes it into a folder you chose on your own computer. See below.
  • The words you put on the field. Typed text is turned into particles locally. It is not sent anywhere — unless you save it as a Text Preset while signed in, which is covered below.
  • Your takes, and the videos rendered from them. This is how recording works: there is no other export, and nothing about either leaves your computer. The video is rendered, encoded and packaged into an MP4 by your browser, into the folder the take is in. It never touches a server of ours or anyone else's. A take is a recording of a performance — every control you move, the text you show, the pictures you give the Gallery and Iris styles, and the sound from your live input or the track you loaded — written as ordinary files into a folder you choose on your own computer, and rendered into a video there later. None of it is uploaded, and we never see it. The only thing the browser keeps is which folder you chose, as a handle it can reopen; it is forgotten when you sign out, and clearing this site's data forgets it too. The takes stay in the folder either way, until you delete them.
  • Snapshots. Pressing Snapshot keeps a few seconds of the performance in memory so the image can be rendered at full size afterwards. That happens entirely in your browser, nothing about it is written to your device, and it is gone the moment you close the tab. When you save one, your browser asks you where to put it and writes the image there. It never touches a server of ours or anyone else's, and we never see it.
There is one thing that does leave, and only because you send it. The updates panel has a box for writing to us. A note you type there, and an image you choose to attach to it, reach us when you press Send — that is the point of the box. Nothing is attached for you, nothing is grabbed from your screen, and closing the panel without pressing Send sends nothing. What a note carries is listed in full below.

The only network requests the application makes are to our own domain and to our database provider — with one exception you cause yourself: when you open the sign-in window, your browser loads Google's sign-in button from Google, so Google sees that the window was opened and your IP address, whether or not you then sign in with Google. Nothing loads from Google before that. The same is true of paying: nothing from Stripe is loaded in the application. Pressing a Headliner price takes your browser to Stripe's own checkout page, and Manage subscription to Stripe's own billing page — pages of theirs, which you are then on, not requests made by ours. There is no advertising, no profiling, no cross-site tracking, and no third-party analytics or tag manager of any kind. Even the fonts are served from our own domain rather than a font CDN, specifically so that loading the page does not hand your IP address to a third party.

The front page counts nothing. It sends no events and writes nothing to your device; the one thing it does is look, on your own device, for whether you are already signed in, so it can stop offering you a Sign in button. When you follow one of its links into the application, the name of the site that sent you to the front page, if there was one, goes with you — a hostname and nothing else — so the application can count where visitors come from, as described under referrer_host below.

What we collect from everyone

One thing: anonymous usage events, so we can tell how many people arrive and find that their browser cannot run the product at all. That number is otherwise unknowable — a visitor whose graphics card is refused sees an explanation and leaves, and nothing records that they came.

You are not identified, and you are not counted twice

Each event carries a random session identifier generated when the page loads. It exists in memory only. It is not written to your device — not a cookie, not local storage, nothing — so it is gone when you close the tab, and two visits by the same person cannot be connected. We do not know that you have been here before, and we have no way of finding out.

The complete list of what a row can contain

The database table has twenty-two columns and no others. Seventeen of them are optional and most are empty on any given row. There is no free-text column, no jsonb blob, and no field a preset name, a filename or anything you typed could be written into — not as a policy, but because the column does not exist.

ColumnWhat it holds
session_idThe in-memory identifier described above.
nameWhich of twenty-seven fixed event names this is — for example that a session started, that a style was chosen, that a take was recorded, that a render of one finished or failed, or that the guided tour was opened and how far it got. A take records its shape, never its length or its contents. Four of the twenty-seven belonged to the old real-time recorder and are no longer sent by anything; the table still knows the names.
atThe time the row reached the server. Server time, not your clock.
app_envWhether the row came from the live site, a preview build, or a developer machine.
browserOne of: chrome, edge, safari, firefox, other. The family only — no version number, no user-agent string.
webgpuWhether your browser offers the graphics API the product needs.
gpu_vendorA vendor bucket — apple, intel, nvidia, amd and a few others. Not a model, not an adapter string.
viewportOne of four size buckets: sm, md, lg, xl. Not your window dimensions.
referrer_hostThe hostname you arrived from, if any — or, if you came through our front page, the hostname that sent you there. Capped at 64 characters. No path, no query string, no fragment.
failureWhich of the five "this will not run" screens you were shown, if you were shown one.
styleWhich built-in visual style was active — a short lowercase name from a fixed set.
verdictNothing writes this any more. It held the result of a readiness check the old real-time recorder ran before it started; that recorder has been replaced by takes and renders, and the column is empty on every row written since.
aspectThe export shape: 16:9, 9:16, 1:1 or 4:5.
sourceWhether the audio was our bundled demo track or a file of your own. Never which file.
reasonIf a render failed, which category of failure. A code from a fixed list, never an error message.
fps30 or 60.
duration_sNothing writes this any more either. It held the length of a recording the old recorder capped at sixty seconds; a render has no such cap, and its length is not recorded at all.
seqA counter on the periodic "still here" event.
user_idYour account, once you have one and are signed in. Absent from every row written before you signed in, and from every row written by anyone without an account.
providerWhich sign-in button was pressed — google or email — and nothing about who pressed it. Set on that one event only.
tour_stopHow far through the guided tour you got — a small number naming one of its stops, and nothing about what you did there. Set on that one event only.
idA row number, assigned by the database.

While a tab is visible and in the foreground, the page sends a small “still here” event every thirty seconds. That is how session length is worked out — the gap between the first and last event — rather than by recording when you leave. It stops while the tab is hidden, so it measures time somebody was actually looking.

Your IP address

It is not in the table above and we do not store it. But it is unavoidably visible to the server the events are sent to, and our database provider records it in its own request logs, along with coarse location derived from it (country and city) and the browser's user-agent string. Those logs are kept for a short period set by our plan — currently one day — and then discarded. We do not export them, analyse them, or join them to anything.

This is true of any hosted service and we would rather say it than let the table above imply otherwise.

What changes when you sign in

An account is optional. Everything the product does visually — every style, every parameter, text, your own audio, the second-screen output — works without one. Signing in is needed to keep presets and to record video.

What we then hold

  • Your email address, from Google. Signing in with Google also returns your name and the URL of your profile picture, which are stored on your account record by our authentication provider. Curl Flow itself only ever reads and displays your email address. We never receive your Google password.
  • Your presets. Both kinds — visual presets and text layouts. These are documents you authored, so they contain whatever you put in them: the names you type, and for a text layout, the words you put on screen and where you placed them. Only you can read them; the database enforces that per row, not the application.
  • Your plan. One word — free (Soundcheck) or Headliner, and whether Headliner was paid for or given to you by us. Alongside it we may keep a short private note to ourselves about why an account was set the way it was. That note is written by us, not by you, and it is not readable through the app — the database refuses it to your own account, not just to everybody else's. You can ask us for a copy of it, like anything else here; see Your rights.
  • The saved state of the picture. When you save a visual preset we also keep the position and speed of every particle at that moment, so that loading it later restores what you were looking at rather than starting the animation over. It is a block of numbers — a few hundred kilobytes to a few megabytes — with nothing in it you typed and nothing that describes you. It is deleted when you delete the preset, and with everything else if you delete your account.
  • Notes you send us. If you write to us through the updates panel we keep what you wrote, and the image if you attached one — stored exactly as you sent it, not re-encoded. A note also carries five things you did not type, and this is all of them: your email address, the style you were on, the version of the app you were running, your browser's user-agent string, and the make of your graphics card, together with the size of your window. The form says so on screen, above the button. That is how “Silk, Safari, Intel graphics” turns a complaint into something we can fix. Only we can read any of it — the database refuses it even to you, because there is no history of your notes in the app. It is never shown to other users, it is never used for anything but answering you and improving the product, and it is deleted with your account.
  • When you last opened the updates panel. One timestamp, written by our server rather than by your browser, so the icon knows what is new to you. That is the whole of it: not what you read, not how long you looked, not whether you looked twice.
  • A nickname and an avatar, if you set them. Both are optional and neither is asked for when you sign up. The nickname is whatever you type, has to be unique, and is the one thing here you choose rather than we observe. The avatar is not a file: it is a number from 0 to 9 saying which of ten pictures we drew you picked, so there is no image of you on our servers and nothing was uploaded. Nobody else can see either of them today — there is nowhere in the product they appear to another person — and if that changes, this page changes with it.
  • If you buy Headliner, a small record of the purchase: which customer you are at Stripe, your subscription and its state (running, cancelled, the date it renews or ends) if you pay monthly, and a reference to the payment if you bought Forever. We never receive your card number or bank details — you type those into Stripe's page, not ours, and they stay with Stripe. Your receipts come from Stripe too, under the name Link, because Stripe is the seller of record (see below).
  • A session token, in your browser's local storage, so you are still signed in when you come back.

Your events, once you have an account

From the moment you are signed in, the usage events described above carry your account identifier as well. That is what lets us see returning use at all, and it is the reason it was not built until there was an account to attach it to.

Events recorded before you signed in stay anonymous. They were written with no account identifier and are not linked to you retroactively — there is nothing to link them with, because the session identifier they carry was never stored anywhere.

If you partner with us as a producer

Producers who promote Curl Flow with their own code sign a partnership agreement through a private link we send them. For that agreement we keep your name, artist name, email, address and country — and, if you sign for a company, its name, registry code and VAT number — together with the agreement you signed, the sales made with your code, and what we paid you. We use it only to run the agreement and keep our accounts, we keep it for as long as accounting law requires, and you can ask for a copy or a correction at the address under Contact. The people who buy with your code are never named to you.

Where it is kept, and who else touches it

WhoWhat forWhere
SupabaseThe database and the sign-in service.Our project runs in eu-central-1, Frankfurt, Germany. Supabase Pte. Ltd. is a Singapore company.
VercelHosts the website. It serves files; it holds no account data and no events.Served from whichever of Vercel’s regions is nearest you — inside the EEA for European visitors. Vercel Inc. is a US company and this project’s origin region is in the United States.
GoogleSign-in only. Its button is loaded from Google when you open the sign-in window; you are signed in through Google only if you choose it. Google is not used for anything else on this site.Google Ireland Limited for users in the EEA, with Google LLC in the United States.
StripePayments for Headliner. Stripe sells Headliner to you on our behalf, as the seller of record under the name Link: it takes the payment, charges and pays the VAT, sends your receipts and handles refunds and disputes. For that it collects your email, name, billing address and payment details itself, as a controller in its own right under its own privacy policy. It tells us that you paid, and nothing about your card.Stripe Technology Europe, Limited, in Ireland, with Stripe, Inc. in the United States.
ResendDelivers the email with your sign-in code, if you sign in by email. It sees your address and that email, and nothing else.Sent from Resend’s EU region, in Ireland. Resend, Inc. is a US company.

Each of those engages its own suppliers in turn — most relevantly, the cloud provider holding the database in Frankfurt, and the network Supabase's API is served through. Their current lists are published on their own sites and we cannot keep an accurate copy of them here.

Transfers outside the EEA

The data itself sits in Frankfurt. The companies operating the infrastructure do not: Vercel Inc. and Resend, Inc. are in the United States and Supabase Pte. Ltd. is in Singapore, and all three have staff and systems that can reach the services they run for us. Their agreements incorporate the European Commission's Standard Contractual Clauses for those transfers. Stripe is not one of them: what you give it at checkout it holds as a controller in its own right, and its own policy covers where that goes.

How long we keep it

WhatHow long
Usage events90 days, then deleted. This is done by a scheduled job inside the database that runs every night, not by somebody remembering — the deletion happens whether or not anyone is paying attention.
Your presets and email addressUntil you delete your account. They are not on the 90-day schedule and are not deleted automatically — they are the thing you made an account in order to keep.
Your plan and any note about itUntil you delete your account. One row, deleted with everything else.
Your nickname and avatarUntil you change them, or until you delete your account. They sit in the same row as your plan and go with it.
The record of a Headliner purchaseUntil you delete your account; a running monthly plan is cancelled first. Stripe keeps its own record of the payment for as long as the law it is under requires, which is separate from ours.
Notes you send us, and any image attachedUntil we delete them, or until you ask us to. They are not on the 90-day schedule, because a note is a conversation we may still be in the middle of. They go with your account if you close it.
When you last opened the updates panelUntil you delete your account. One timestamp, one row.
Your session tokenUntil you sign out, or it expires.
Provider request logs (including your IP)A short period set by our plan, currently one day.

Deleting your account removes your presets, your nickname and avatar, your plan and any note about it, our record of any Headliner purchase — cancelling a running monthly plan first, so nothing is charged again — and anything you sent us through the updates panel — including an attached image, which is a file in storage rather than a row and is removed explicitly. Your past events are not deleted — they are un-linked, so what remains is exactly the anonymous row it would have been had you never signed in.

Why we are allowed to hold each of these

WhatLegal basis
Usage eventsOur legitimate interests, Article 6(1)(f) — knowing whether the product runs on the machines people actually arrive with. We think the balance falls our way because there is no identifier, nothing that survives your visit, nothing you typed, and it is all gone in 90 days. If you disagree, you can object; see below.
Your account, presets and sessionPerformance of a contract, Article 6(1)(b). You asked for an account so that things would be kept; keeping them is the thing you asked for.
Your plan, and the record of a purchasePerformance of a contract, Article 6(1)(b). If you bought Headliner, knowing that you did is how you get it.
A note about your planOur legitimate interests, Article 6(1)(f) — remembering our own decisions about individual accounts, such as a gift. It is one sentence, only we can read it, and it goes when the account does.
Notes you send usOur legitimate interests, Article 6(1)(f) — answering the person who wrote to us, and fixing what they told us about. You chose to write it and pressed Send; the balance falls our way because nothing is collected unless you do, the technical details are listed on the form before you send it, and the whole of it goes when your account does.
Sign-in with Google, or with a code by emailThe same — it is how you asked to sign in.

Cookies, and why there is no banner

There are no cookies. Not necessary ones, not analytics ones, not any. The word does not appear in the product.

For local storage the rule is unusually strict, and it is enforced in one place in the code rather than left to whoever writes the next feature:

  • If you are not signed in, nothing is written to your device at all — except the things you explicitly ask for: a preset you press Save on, the sign-in itself, and the takes folder you pick in your browser's own folder dialog. Anything a previous visitor left behind is cleared when you arrive, so the product behaves identically on every visit because there is nothing for it to behave differently from.
  • If you are signed in, your session token and your working state — the layout you left, which panel sections you had open, whether you have already taken the guided tour — are kept, so you can pick up where you left off. Saving a preset also keeps the state of the picture beside it, which is much larger than the preset itself and is held under the same rule.
This is why you have not been asked to accept anything. A consent banner exists because a site stores or reads something on your device that it does not strictly need. For a visitor without an account, this one stores nothing at all, so there is nothing to ask about. We would rather build it that way than ask you to click past a dialogue.

Your rights

Under the GDPR you can ask us for a copy of what we hold about you, to correct it, to delete it, to receive it in a portable form, or to object to us holding it at all.

What that actually involves, honestly

Deletion you can do yourself, now. Open the Curl Flow menu in the top-left corner, click your account, and use Delete my account at the bottom. It tells you exactly what will go before you confirm, and it is not reversible. Nothing is queued for us to get round to: the files are removed first and the account itself only goes once they are, so a deletion that fails half way leaves your account working rather than leaving your files behind.

For the rest — a copy of what we hold, a correction, an objection — email support@curlflow.eu from the address on your account and we will do it by hand, within 30 days and usually much sooner.

Two things are worth knowing before you ask:

  • We cannot find your anonymous events, and neither can anyone else. They carry no identifier that survives a visit, so there is no way for us to work out which rows were yours. The GDPR anticipates this: where a controller genuinely cannot identify a person, the access, correction and deletion rights do not apply to that data. We are not going to start storing an identifier in order to be able to delete it later.
  • You can already export your presets yourself. Every preset has an Export button that writes a JSON file to your machine, and the same file can be imported anywhere. You do not need to ask us, and you do not need an account to do it.

If you are unhappy with how we have handled something, you can complain to the Estonian Data Protection Inspectorate, Andmekaitse Inspektsioon, at aki.ee. We would rather you told us first.

Changes to this page

The date at the top is the date this version took effect. If we change something that affects people with accounts, we will email them; we have no way of reaching anyone else, which is rather the point of the rest of this page.

Contact

Siin App OÜ, Sõle tn 82-14, 10314 Tallinn, Harju maakond, Estonia — support@curlflow.eu