Anonymize a CSV file

Runs locally in your browser. Your file never leaves your device.

By processing a file or pasted text here, you agree to the Terms.

Drop a .csv file here — or

Customer exports, data samples — CSV/TSV, up to 20 MB. A large file can pause this tab for a few seconds while it is scanned; everything stays local.

…or paste CSV instead
Free-text scan patterns

These patterns are scanned across free-text, email, and IP columns. The engine’s own column categories — phone numbers, card numbers, names, addresses, and IDs — are controlled per column in the review table below, not here.

Sharing a data sample is where PII leaks

Someone asks for “a sample of the data” — a vendor debugging an import, a colleague on a ticket, an AI chat you want to reason over the shape of a table. So you export a few hundred rows to CSV and attach it. The trouble is that a customer export is mostly personal data: an email column, a phone column, full names, sometimes a card number or a government id, and a free-text notes field where anything can end up. Deleting the sensitive columns breaks the sample — now the joins don’t line up and the counts are wrong — so people share the real thing and hope nobody minds. This page is the middle path: keep the shape of the data, remove the identities.

How this anonymizer works

It parses your CSV into columns and classifies each one. A column is masked when its header names a PII category — email, phone, credit_card, ssn, first_name, address, date_of_birth, customer_id — or when a supermajority of its values match a tight shape: an email, an IP address, a phone number, a Luhn-valid card, a dashed SSN. The column-level gate is deliberate: one cell that looks like a phone number proves nothing, but a column that is 95% phone-shaped is a phone column. Every other column, free-text notes included, is still scanned cell by cell by the same engine that powers this site’s log file redactor, so an email or a password=… credential sitting in a comment is caught too.

Masked values become consistent placeholder tokens, and the same value always becomes the same token. A customer who appears in five rows is the same [ID-1] in all five; an email that shows up in an email column and again in a notes cell is the same [EMAIL-1] in both. That is what keeps the sample usable — joins, groupings, and counts survive, because referential integrity is preserved. This is tokenize-only by design: you get stable tokens, not fake-realistic lookalikes, because a fake name that reads as real is a liability, not a feature. The output is valid CSV with the same delimiter, the same columns in the same order, the same header text, and every byte outside a masked cell left exactly as it was.

Column-level detection, and what it isn’t

The conceptual reference for a PII anonymizer is Microsoft Presidio, whose recognizer categories — person, email, phone, credit card, national id — shaped the vocabulary here. The honest difference: Presidio is a Python NLP library and service that reads free-running language to find a name in the middle of a sentence. This tool does column-level pattern matching in your browser, which is narrower on purpose. It is very good at “this whole column is phone numbers” and has no opinion about “the third word of this comment is a surname.” Naming that limit is the point — a tool that claimed to catch every name in every free-text field would be lying, and you would trust it exactly when you shouldn’t.

What it can miss — read this before you share

Detection is pattern-based and best-effort — expand for what can slip through.

Detection is pattern-based and incomplete by construction. A PII column under a bland header (owner, contact, a vendor-specific name) with no tell-tale value shape is only masked if you flag it in the column table. A free-text field can hide a name or an address the scanner has no pattern for. Bare numeric ids are deliberately left alone — a 10-digit number is far more often an order id than a phone — so an identifier you consider sensitive may need a manual override. And the tool can over-mask: a column named city is treated as an address, and a review-flagged column defaults to masking, because masking too much is the safer failure. The column table and the side-by-side preview exist so the final human pass — the one no tool replaces — takes a minute, not an afternoon.

This page, the JSON redactor, or the log redactor?

Reach for this page when the data is tabular — a CSV export where PII sits in columns. When it is nested — an API response, an export, a webhook payload — the JSON redactor walks the tree by key name and pattern instead. When it is free-running text — a log, a stack trace, a paste — the log file redactor scans it line by line. Same detection core, same trust story; different file shapes.

Practical limits

Files are processed entirely in this tab’s memory with a 20 MB ceiling. Scanning runs on the page’s main thread, so a large file can pause this tab for a few seconds — nothing is being uploaded during that pause; there is no network activity at all, which you can verify in DevTools. The page works offline once loaded, and nothing persists after the tab closes.

Frequently asked questions

What gets masked, exactly?

Whole columns, by two kinds of evidence. A column is masked when its header names a PII category (email, phone, credit_card, ssn, first_name, address, date_of_birth, customer_id and relatives) or when a supermajority of its non-empty values match a tight shape — email addresses, IPv4/IPv6, phone numbers, Luhn-valid card numbers, or dashed SSN shapes. Every remaining column, including free-text notes and comments, is scanned cell by cell with this site’s shared pattern engine, so an email or a password= credential hiding in a comment is caught too. Masked values become consistent placeholder tokens like [EMAIL-1] or [PHONE-2]. Long random-looking strings that match nothing are flagged for your review — not changed — with the line they live on.

Does this page upload my CSV anywhere?

No. This is a static page with no server behind it, and its Content-Security-Policy is set to connect-src ‘none’ — the browser itself refuses to let this page make any network request, to us or to anyone. You can verify that: open DevTools, watch the Network tab, and load your file — no request carries your data. Everything runs in this tab’s memory and nothing persists after you close it.

Do the masked values keep the sample usable?

Yes, that is the point of tokenizing rather than deleting. Tokenization is deterministic: the same value anywhere in the file always becomes the same token, so a customer who appears in five rows is the same [ID-1] in all five, and a join key that links two columns still links them after masking. Your grouping, counting, and joining all still work on the shared sample — the numbers are real, only the identities are gone. This tool is tokenize-only by design: you get stable tokens, not fake-realistic lookalikes, because a fake name that looks real is a name someone can mistake for a real one.

Can it miss PII, or mask the wrong column?

Both, and the copy says so rather than pretending otherwise. Detection here is column-level pattern matching — narrower by design than a natural-language PII recognizer like Microsoft Presidio, which is a Python library or service, not a paste-and-go browser tool. A free-text column of names with a bland header (owner, contact) is only masked if you flag it; a bare 10-digit id is left alone on purpose, because it is far more often an order number than a phone. It can also over-mask: a column named “city” is treated as an address even when a cell holds something else, because masking too much is the safer failure. The column table shows exactly what was detected and why, with a per-column override, so the final human review — the step no tool can replace — is fast.

What about semicolons, quotes, BOMs, or a file with no header?

The parser is RFC 4180-aware: it sniffs the delimiter (comma, semicolon, tab, or pipe) and whether the first row is a header, both of which you can override if it guesses wrong. Quoted fields, doubled "" quotes, embedded commas and newlines, a byte-order mark, and CRLF vs LF line endings are all preserved — everything outside a masked cell stays byte-identical, and the output is valid CSV with the same delimiter, columns, and header text. Ragged rows (a row with too few or too many fields) are anonymized by position and reported, never dropped.

This page, the JSON redactor, or the log redactor?

Use this page for tabular data — a CSV export where PII lives in columns. For nested API responses, exports, or payloads, the JSON redactor walks the tree by key and pattern. For a log or any free-running text, the log file redactor scans line by line. All three share the same detection core and the same connect-src ‘none’ trust story; they differ only in the shape of the file they understand.