All posts

Download statistics without tracking the people who download

You want to know whether the file you sent arrived. The person who opened it does not want to be followed around the internet. A share link in Nemi records a time and a salted, shortened hash of the address it came from, and nothing about the browser or the device unless you switch on Trace for that one link. Hash an address below and try to reverse it.

Privacy · · updated · 7 min read

When you send somebody a file, you want to know one thing: did it arrive? The person on the other end wants something too, which is not to be followed around the internet because they opened a link. Both can be true at once, and this post is about how a Nemi share link manages it.

What does Nemi record when somebody opens a shared link?

Less than you might expect, and the same for everybody who opens it. Every open and every download records a time, which file it was and whether it was a preview or a download. It records a hash of the address the request came from, salted and shortened, so that ten opens from one person count as one visitor. And the file's download count goes up by one. That is the list. No browser, no device, no location, no referrer.

A sender can choose to know more about one particular link, by switching on Trace for it. That changes the list, considerably, and the toggle below shows exactly how.

What one visit leaves behind

4 things kept per visit

Recorded

  • When

    The time of each open and each download.

  • Which file, and how

    Whether it was previewed in the browser or downloaded.

  • A salted, shortened hash of the address

    So two opens from one place count as one visitor. Never the address itself.

  • A download count

    On the file, and a download record with no address and no browser in it.

Never recorded

  • The IP address itself
  • Browser, device or system
  • Location
  • Where they came from
  • How long they read

This is every share link unless the sender chose otherwise. The sender sees counts and times, never who. Either way it is deleted with the link.

Each line restates sections 3.6 and 3.10 of the privacy policy, which is what a recipient is told. Where the two ever differ, the policy is right.

How do you count visitors without storing their address?

To say "three people opened this" rather than "this was opened eleven times", you need some way to tell one visitor from another. The obvious handle is the IP address, and the obvious mistake is to store it. An address is personal data: it can point at a household, and stored next to a time and a file it says who looked at what.

So Nemi no longer stores the address for an open or a download. The moment a request arrives, the server puts a secret salt in front of the address, runs the two through SHA-256, keeps the first 40 hexadecimal characters and drops the rest. Two opens from the same address produce the same hash, so they can be counted as one visitor, and nothing Nemi writes today says what the address was.

From an address to a hash, on every open

Address203.0.113.42Salteds3cr3t|203.0.113.42SHA-2569c41e07b...a2f6 (64)Stored9c41e07b...d18e (40)

1/4A request arrives

Every request to a server carries the address it came from. That cannot be avoided; the reply has to go somewhere.
This happens inside the request, before anything is written. The address itself is held in memory only as long as the request, and our rate limits, need it.

Try it. Type an address, change the salt, and then play the attacker.

Hash an address, then try to get it back

SHA-256 of salt, a bar, and the address

The first 40 characters are kept, 160 of the 256 bits. The rest is thrown away, and so is the address.

Now try to reverse it

A hash cannot be run backwards, but an attacker can run it forwards on every likely input and look for a match. This tries the 65,536 addresses that start with the same two numbers.

The same construction our server uses, rebuilt on your browser's WebCrypto with a salt this page made up. The search really runs, in your browser, and nothing you type leaves this page. 203.0.113.42 is an address reserved for examples.

Does shortening the hash make it anonymous?

No, and it is worth being exact about why, because this is where descriptions of hashed analytics usually go soft. Cutting a SHA-256 hash to 40 characters keeps 160 bits. There are about 4.3 billion IPv4 addresses, which is 232. Spread over 2160 possible values, the chance that any two of them share a stored hash is about one in 297, a number with 30 digits. In practice every address still gets a hash of its own. The shortening keeps the column small. It protects nobody.

What protects the address is the salt. As the search above shows, an attacker who knows the salt can hash every possible address and look the stored value up: 4.3 billion is a large number for a person and a modest one for a computer. Without the salt there is nothing to try, because every guess at the address has to be paired with a guess at a secret that is not written anywhere they can read. So the salt is configuration held outside the code and outside the database, and is never published.

The honest word for the result is pseudonymous, not anonymous. On one link, we can still tell that the same visitor came back, which is the whole point of counting visitors. What a stored hash cannot do, without the secret, is tell anybody who that visitor was.

0

raw IP addresses stored today for an open or a download

160 bits

of the hash kept, of 256

4.3 billion

IPv4 addresses: few enough to try them all, if the salt were known

How do I see who downloaded my file?

On an ordinary link you see how often it was opened and downloaded, when, and by roughly how many visitors, but not who they were. To know more about one delivery, you switch on Trace. It is for the delivery where knowing matters: a contract, a pitch, a proposal you need to follow up on. It is off unless the sender chooses it, it is set per link rather than per account, and the sender sees in plain words what it will record before they create the link. With it on, a visit also records the country and city the address resolves to, the kind of device, the browser and operating system, the site that sent the visitor, how long the browser reports they spent on each page, a short code on every download so a leaked copy can be traced to it, and the visitor's email address if the sender typed it for that link.

Even then, a few things keep it from becoming tracking across the web:

  • The raw address is still not stored. The same salted hash is used, and location comes from the network, never from the browser's location prompt.
  • Repeat visits are grouped per link. The key that ties one viewer's visits together includes the link itself, so the same browser opening two of your links produces two unrelated keys. The only way a sender sees one person across several links is by an email address they typed themselves, and never across senders.
  • Facts and estimates are kept apart. Opens and downloads are recorded by our server and are exact. Reading time is measured in the visitor's browser, counted only while the file is in front of them, and shown to the sender as an estimate.
A share link should tell you the file arrived, not who the person is.

How long is any of this kept?

Exactly as long as the link. Share statistics, including everything Trace records, live with the share they belong to and are deleted with it, and revoking a link erases its trace at the same moment. Nothing about the people who opened it outlives the link.

The full detail, written for the person who opened a link rather than the person who sent it, is in the privacy policy. How to switch Trace on and read what it shows is in the help centre and on the Trace page, and everything else a share link can do is on the Files page. If the link is for a large delivery, the guide to sending large files securely covers the settings worth choosing, and a link sent from your own domain records exactly the same as any other.

Questions people ask

Can I see who downloaded my shared file?

On an ordinary Nemi share link you see how many times it was opened and downloaded, when, and roughly how many different visitors there were, but not who they were. If you need to know more for one particular link, you can switch on Trace for it, which adds location, device, browser, reading time and a code on each download. A person is only named when you typed their email address for that link yourself.

Is a hashed IP address anonymous?

No. A hashed address is pseudonymous: the same address always gives the same hash, which is what lets visits be counted, and anybody who knows the salt can try every possible IPv4 address and find the match. What protects it is keeping the salt secret. Nemi keeps the salt out of the code and the database and never publishes it.

Is an IP address personal data?

In the EU it is generally treated as personal data, because it can point to a household or a person, especially next to a time and a file. That is why Nemi no longer stores the address for an open or a download, only a salted and shortened hash of it. Our privacy policy sets out exactly what is recorded about people who open a link.

What does Trace record about the people who open my link?

With Trace on, a visit to that one link also records the country and city the address resolves to, the kind of device, the browser and operating system, the referring site, how long the browser reports was spent on each page, a code on every download, and the email address if you typed it for that link. The raw IP address is still not stored, and visits are grouped by a key that only works on that link.

Does the person who opened my link know about Trace?

Nemi's privacy policy tells everybody who opens a link exactly what Trace can record. Switching it on is the sender's decision about somebody else's data, so our Terms make the sender responsible for having a lawful basis and for telling the people they send it to, and forbid using it covertly where the law requires telling them.

How long are download statistics kept?

As long as the link. In Nemi, share statistics, including everything Trace records, are deleted together with the share they belong to, and revoking a link deletes its trace at the same moment.

Will I be told when somebody opens my link?

Yes. Nemi notifies you in the app the first time each of your links is opened. That notification says only that the link was opened, never who opened it.

Where the numbers come from

  • The salted hash, cut to 40 hex characters: lib/share-open-tracking.ts (hashViewerIpForShareAnalytics, recordShareContentOpen)
  • What a download records without Trace: app/api/download/file/[fileId]/route.ts
  • What Trace adds, and the per link viewer key: lib/share-trace.ts (traceViewerKey, traceCoarseLocation, traceReferrer)
  • What recipients are told: /privacy, sections 3.6 and 3.10
  • Share statistics, not tracking: /security

Read next

Use the thing we write about.

Files, docs, sheets, photos, calendar and meetings in one account.