Data Anonymizer, Explained
After reading this you will know how to strip direct identifiers from a CSV while keeping joins and group-bys intact, and you will understand why that is pseudonymization rather than true anonymization.
What the tool does
The Data Anonymizer takes a CSV and applies a per-column rule: keep the column as is, mask part of each value, replace values with a one-way hash, swap in realistic fake data, or drop the column entirely. It writes a new CSV you can share.
The property that makes it useful is consistency. If the email [email protected] appears in 40 rows and you hash it, all 40 rows get the same token, for example a1b2c3d4. A different email gets a different token. So a query like "count orders per customer" returns the same counts on the anonymized file as on the original, even though no real email survives.
Here is the hook. Suppose you have a support log with a name column and you mask it. The value Jan becomes J**, and John becomes J***. Same first letter, same length signal, no full name. You can still eyeball the data and demo it to a colleague, but you have removed the plain text most people would recognize.
When to use it, and when not to
Reach for this when you need to hand a dataset to someone who should not see raw identifiers: a contractor debugging a pipeline, a support ticket attachment, a public sample, a bug report on a forum. In all of these the analytic shape matters (row counts, distributions, how tables join) but the actual names and emails do not.
Do not treat the output as safe to publish widely if the remaining columns are specific. A row that reads ZIP 90210, age 71, diagnosis rare-X can point at one real person even with the name hashed. Masking a name does not fix that.
Masking and hashing direct identifiers is pseudonymization, not anonymization. Rare combinations of the columns you kept can still single out an individual. If the audience is untrusted or public, drop or generalize quasi-identifiers (exact ZIP, exact birth date, exact salary) as well.
The five column actions and what they cost
- Keep
- The value passes through unchanged. Use it for non-sensitive columns you need at full fidelity, like
order_totalorcountry. - Mask
- Show a few edge characters, replace the middle with a fixed symbol.
JanbecomesJ**. Readable and reversible only by guessing, but it leaks length and first letter. - Hash
- Run the value through SHA-256 and keep a truncated prefix. One-way and consistent. The best choice when you need joins to keep working but want no readable identifier.
- Fake
- Replace with a plausible generated value of the same type (a fake name for a name, a fake email for an email). Reads naturally in demos and screenshots.
- Drop
- Remove the column. The only action that fully removes the information rather than transforming it.
Only two of these are truly hard to reverse: hash and drop. Mask leaks structure. Fake looks anonymous but, if the tool maps the same input to the same fake value, the mapping itself is a table an attacker could try to rebuild.
How consistent hashing works
SHA-256 turns any input into a 256-bit digest, written as 64 hexadecimal characters. The function is deterministic: the same input always yields the same digest. It is also one-way in practice, meaning you cannot run it backwards to recover the input.
Here v is the raw cell value, \text{SHA256}(v) is the full 64-character digest, and n is how many leading hex characters the tool keeps as the token t. Truncation trades collision safety for shorter tokens.
Collision risk grows with how many distinct values you hash. With n hex characters you have 16^n possible tokens. By the birthday approximation, the chance that k distinct inputs produce at least one collision is roughly:
Work an example. Keep 8 hex characters, so 16^8 = 4.295 \times 10^9 tokens. With k = 1000 distinct emails, the exponent is -1000^2 / (2 \times 4.295 \times 10^9) = -1.164 \times 10^{-4}, so P \approx 1.164 \times 10^{-4}, about 1 in 8,600. At k = 100{,}000 distinct values it climbs to about 0.686, roughly 69 percent. Lengthen the token when you have many distinct values.
A worked example on the demo data
Anonymizing a customer table
Click the demo button to load a small customer CSV. The relevant columns are name, email, country, and spend. Apply mask to name, hash to email, keep for country and spend.
- Row 1 reads
Jan,[email protected],NL,120. The nameJanmasks toJ**. The email hashes to a token, saya1b2c3d4. Output:J**,a1b2c3d4,NL,120. - Row 2 reads
Jana,[email protected],NL,80. Different email, different tokene5f6a7b8. Output:J***,e5f6a7b8,NL,80. - Row 3 reads
Jan,[email protected],NL,45. Same email as row 1, so the same tokena1b2c3d4comes back. Output:J**,a1b2c3d4,NL,45.
Now group by the hashed email and sum spend. Token a1b2c3d4 totals 120 + 45 = 165, exactly what you would get grouping the original file by [email protected]. The join key changed, the answer did not.
Notice the masked names. J** and J*** differ in length, which reveals that the second name is one character longer. That is a small leak, but on a column of first names it can narrow guesses.
Reading the output and checking it is right
Three quick checks tell you the transform behaved.
First, row count. The anonymized file must have the same number of rows as the input. Anonymization changes cells, never the number of records.
Second, distinct count on hashed columns. Count distinct emails in the original and distinct tokens in the output. They should match unless a collision occurred. In the demo, 2 distinct emails give 2 distinct tokens.
Third, aggregate agreement. Pick a group-by that only uses kept columns plus a hashed key, and confirm the totals match the original. If spend per token equals spend per email, joins survived.
Common mistakes
Before you share, ask which single column or pair of columns would let you recognize one row. If the answer is easy, generalize or drop those columns too, not just the name.
Hashing a column that has very few distinct values gives false comfort. If gender has two values, hashing produces two tokens, and anyone can map them back by frequency. Hash identifiers, not tiny categories.
Keeping a free-text column often defeats the whole exercise. A notes field can contain names, phone numbers, or addresses in the middle of a sentence. Drop free text or review it by hand.
Masking dates and IDs by keeping the ends still leaks a lot. A masked order ID like ORD-****-2024 reveals the year. Prefer hash or drop for structured identifiers.
Do not forget the header row and file encoding. If the source came from a spreadsheet, stray BOM bytes or smart quotes can survive into your shared file. Clean the CSV first, then anonymize.
Related tools
Anonymizing is usually one step in a larger flow. Inspect and trim a file first with the CSV Viewer & Editor, which lets you sort, filter and extract columns before you decide what to mask. If your data starts in a spreadsheet, convert it with the Excel → CSV Converter so each sheet becomes clean CSV. To reshape the anonymized result for an API or a config file, use the CSV ↔ JSON Converter. When the source is a columnar file, preview it with the Parquet & Feather Preview before exporting to CSV.
Frequently asked questions
Can someone reverse the hashed emails back to real ones?
Not by inverting SHA-256, which is one-way. But if the attacker already has a list of candidate emails, they can hash each one and look for matching tokens. This is a dictionary attack. It works because the same input always produces the same token. For sensitive data, drop the column instead of hashing it.
Will hashing break my joins between two files?
No, as long as both files are anonymized with the same settings, including the same token length. Equal inputs give equal tokens, so [email protected] maps to the same token in both files and the join still matches. Anonymize both together to be safe.
Does this make my data GDPR compliant?
It helps but does not guarantee it. Pseudonymized data is still personal data under GDPR because re-identification remains possible via the remaining columns. Treat masking and hashing as risk reduction, not as a legal green light.
Why do fake values look real instead of random?
Realistic fakes keep the shape of the data so downstream code that validates emails or parses names does not choke. A random string might fail a format check; [email protected] passes. The values are made up, but the format is preserved.
Is anything sent to a server?
No. The tool runs entirely in your browser. Your file and its contents never leave your device, which matters precisely because the input contains identifiers you are trying to protect.