# CSV Cleaner

Clean a messy CSV in your browser: trim whitespace, remove duplicate rows, drop empty rows, fill blanks, and normalize delimiters. No upload, free.

## Run it

- **CLI:** `gizza tool csv-cleaner "name , age
 Alice ,30
Bob,25
,,
Bob,25"`
- **Web:** https://gizza.ai/tools/csv-cleaner/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/csv-cleaner/tool.json

## Inputs

- `data` — CSV _(field)_
- `header` — First row is a header (kept, not deduped/dropped) _(field)_
- `delimiter` — Input delimiter (, tab ; |) _(field)_
- `output_delimiter` — Output delimiter _(field)_
- `trim` — Trim whitespace from every cell _(field)_
- `dedupe` — Remove duplicate rows (first kept) _(field)_
- `drop_empty_rows` — Drop fully-empty rows _(field)_
- `empty_cells` — Empty cells _(field)_
- `fill_value` — Fill value (used when 'Fill' is selected) _(field)_
- `line_ending` — Output line ending _(field)_

## Output

- Cleaned CSV (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `data` — CSV
- `header` — First row is a header (kept, not deduped/dropped)
- `delimiter` — Input delimiter (, tab ; |)
- `output_delimiter` — Output delimiter
- `trim` — Trim whitespace from every cell
- `dedupe` — Remove duplicate rows (first kept)
- `drop_empty_rows` — Drop fully-empty rows
- `empty_cells` — Empty cells
- `fill_value` — Fill value (used when 'Fill' is selected)
- `line_ending` — Output line ending

Example: `https://gizza.ai/tools/csv-cleaner/?data=name%20%2C%20age%0A%20Alice%20%2C30%0ABob%2C25%0A%2C%2C%0ABob%2C25&header=true&delimiter=%2C&output_delimiter=same&trim=true&dedupe=true&drop_empty_rows=true&empty_cells=keep&fill_value=N%2FA&line_ending=lf`

---

## Clean a messy CSV in one pass

Paste a CSV and this tool tidies it locally in your browser — **nothing is
uploaded**. Every cleaning step is an independent toggle, so you can run just the
ones you need:

- **Trim whitespace** — strip leading/trailing spaces from every cell.
- **Remove duplicate rows** — drop rows identical to an earlier one (the first is
  kept).
- **Drop empty rows** — remove rows whose every cell is blank.
- **Fill empty cells** — replace blank cells with a value like `N/A` or `0`.
- **Normalize the delimiter** — re-emit with a comma, tab, semicolon, pipe, or any
  single character.
- **Normalize line endings** — output LF (`\n`) or CRLF (`\r\n`, for Windows/Excel).

A first-row **header** is kept and exempted from dedup, empty-row drop, and cell
fill, so your column names stay intact.

### Worked example

With **trim**, **remove duplicate rows**, and **drop empty rows** all on, this
input:

```
name , age
 Alice ,30
Bob,25
,,
Bob,25
Carol, 40
```

becomes:

```
name,age
Alice,30
Bob,25
Carol,40
```

The spaces around `name`, `Alice`, `40`, etc. are trimmed, the all-empty `,,` row
is dropped, and the repeated `Bob,25` row is removed — the header row stays.

### FAQ

<details>
<summary>Which duplicate row is kept?</summary>

The first occurrence in the file; later identical rows are dropped. Duplicate
matching happens **after** trimming and filling, so ` Bob ` and `Bob` count as the
same row when trim is on.

</details>

<details>
<summary>Is the cleaning case-sensitive?</summary>

Yes. Cells are compared exactly, so `Alice` and `alice` are treated as different
values and won't be deduped together. The tool doesn't change letter case — it only
trims surrounding whitespace when you enable **Trim**.

</details>

<details>
<summary>What counts as an "empty row" or "empty cell"?</summary>

A cell is empty when it's blank or only whitespace. An **empty row** is a row where
*every* cell is empty (for example a stray `,,,` line). Enable **Drop fully-empty
rows** to remove them, or **Fill** to replace individual empty cells with a value.

</details>

<details>
<summary>Can I change the delimiter, or read a tab/semicolon file?</summary>

Yes. Set the **input delimiter** to match your file (a single character, or
`comma`/`tab`/`semicolon`/`pipe`) and pick an **output delimiter** to re-emit with.
Leave the output on *Same as input* to keep the original separator.

</details>

<details>
<summary>Is my data uploaded anywhere?</summary>

No. The whole clean runs locally with WebAssembly; your CSV never leaves your
browser.

</details>

### Limits & edge cases

- Rows may have different column counts — cleaning is per-row and never pads to a
  fixed width. Missing trailing cells are treated as empty.
- Quoted fields are parsed as CSV, so a value like `"a, b"` stays one cell and is
  re-quoted only when the output needs it.
- Turn off **First row is a header** for files with no header row; then row 1 also
  participates in dedup, empty-row drop, and fill.
- Everything is processed in memory, so extremely large files are bounded by your
  browser's available memory.

## Related tools

- [CSV Dedupe](https://gizza.ai/tools/csv-dedupe/): Remove duplicate rows from a CSV, keeping the first — optionally keyed on chosen columns. Runs in your browser, nothing is uploaded, free.
- [Avro to JSON Converter](https://gizza.ai/tools/avro-to-json/): Decode Apache Avro Object Container Files (.avro / OCF) to JSON, NDJSON, or the embedded schema — no .avsc needed, free and private in your browser.
- [Bencode decoder](https://gizza.ai/tools/bencode-decoder/): Decode bencode (the BitTorrent / .torrent serialization format) into readable JSON, and re-encode JSON back into canonical bencode — in your browser. Nothing is uploaded.
- [Change CSV Delimiter](https://gizza.ai/tools/csv-change-delimiter/): Re-save CSV or delimited data with a different separator (comma, tab, semicolon, pipe) with correct requoting — in your browser. Free, private, no upload.
- [CSV Filter](https://gizza.ai/tools/csv-filter/): Keep only the CSV rows that match a condition (e.g. age > 30, city == NYC, name contains al) — numeric or string, in your browser. Free, private, no upload.
