---
title: "How to Redact PII From CSV, Excel, and JSON"
description: "Omit redacts PII inside structured data files, not just documents: CSV and Excel rewrite the cell, JSON rewrites the value in place, and in every case the file's shape survives. Here is exactly what changes and what does not, format by format."
canonical_url: https://omitsys.com/blog/redact-structured-data/
author: "Ranjan Singh"
date: 2026-08-17
updated: 2026-08-23
published: false
---

## In short

A JSON file containing no PII comes out byte-for-byte identical, because only the characters that matched are touched. CSV and Excel cannot make that promise, since pandas and openpyxl rewrite the whole file on save. CSV headers are never scanned, because pandas treats row one as column names rather than data, while Excel has no separate header concept and scans row one like any other row. JSON keys give the detector context but are never scanned or redacted, which is a real gap when a name sits in a key rather than a value.

Omit redacts [PII](/blog/what-is-pii/) inside structured data, not just documents. A CSV or Excel export, or a JSON file from an API or a database dump, goes through the same detection engine as a PDF or an image, and the result comes out the same shape it went in: same rows, same columns, same keys, same nesting. Only the values that matched get changed.

CSV and Excel work cell by cell. Every value in every column is scanned, and a match gets rewritten in that cell, in place, exactly as the file's column policy has it set. Nothing about the file's structure moves.

## Why JSON works differently underneath

JSON works differently underneath, because JSON has no fixed grid to rewrite a cell in. Instead of parsing the file and writing a new one back out, which normalizes spacing and number formatting even when nothing else changes, Omit finds the exact position of every string value in the original text and only touches the characters that actually matched. A JSON file with no PII in it comes out byte-for-byte identical to what went in, not just equivalent to it. That is a stronger guarantee than CSV or Excel can make, because pandas and openpyxl always rewrite the whole file when they save.

## Headers, keys, and where each format draws the line

Where the three formats genuinely differ, and it is worth knowing which one you are handling. CSV headers are never scanned or redacted: pandas treats the header row as column names, not data, so `"Personalausweis"` or `"Note"` at the top of a column is left alone regardless of what it says. Excel is the opposite: a workbook has no separate header concept the way a CSV does, so if row one contains a real name or account number instead of a label, it is scanned and redacted exactly like any other cell. JSON keys sit closer to CSV's behavior: an object's keys are decoded only to give the value they name some context, the same way a CSV column header tells the detector what kind of value it is looking at. A key is never itself scanned for PII and never redacted. If a JSON file has a real name or an email address sitting in a key rather than a value, an automated pass will not catch it, and there is no note in the audit report calling that out yet. That is a real gap, not a hidden one, and it is written up in full in the product repository.

## What stays the same everywhere

Every format keeps the same core rules the rest of the product runs on. The original file is never modified: redaction writes a new file and leaves yours exactly as it was. The write itself is atomic, a temp file followed by a rename, so a crash mid-write cannot leave a half-written file in place of your data. And everything runs on your own machine, with nothing uploaded.

Vault re-identification, the reversible side of redaction, works the same way across all three formats: tokenize a value, get it back later from an authorized project with the same request that redacted it in the first place. That round trip is tested the same way for CSV, Excel and JSON, cell for cell and value for value.
