# CSV Type Inferrer

Paste CSV and get a JSON schema: auto-detected delimiter, header row, and per-column types (int, float, bool, date, datetime, string). Runs in your browser.

## Run it

- **CLI:** `gizza tool csv-type-inferrer "id,name,active,joined,score
1,Alice,true,2021-05-01,9.5
2,Bob,false,2022-11-30,7"`
- **Web:** https://gizza.ai/tools/csv-type-inferrer/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/csv-type-inferrer/tool.json

## Inputs

- `data` — CSV text _(field)_
- `delimiter` — Delimiter _(field)_
- `headers` — Header row _(field)_
- `null_tokens` — Null tokens (comma-separated) _(field)_
- `date_detection` — Detect date & datetime columns _(field)_
- `output` — Output _(field)_

## Output

- Schema + records (JSON) (text)

## Query parameters

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

- `data` — CSV text
- `delimiter` — Delimiter
- `headers` — Header row
- `null_tokens` — Null tokens (comma-separated)
- `date_detection` — Detect date & datetime columns
- `output` — Output

Example: `https://gizza.ai/tools/csv-type-inferrer/?data=id%2Cname%2Cactive%2Cjoined%2Cscore%0A1%2CAlice%2Ctrue%2C2021-05-01%2C9.5%0A2%2CBob%2Cfalse%2C2022-11-30%2C7&delimiter=auto&headers=auto&null_tokens=NA%2CN%2FA%2CNULL%2Cnull%2CNone%2Cnan&date_detection=true&output=both`

---

## About this tool

Paste a chunk of CSV and this tool figures out its structure for you. It sniffs the
**delimiter** (comma, semicolon, tab or pipe) by testing which one splits the rows into the most
consistent number of columns, decides whether the **first row is a header**, and then infers a
**type for every column** — `int`, `float`, `bool`, `date`, `datetime`, `string`, or `empty`. The
result is a JSON schema report plus the rows re-emitted as type-coerced JSON records. Everything
runs locally in your browser; the CSV is never uploaded.

### Worked example

Given this input:

```
id,name,active,joined,score
1,Alice,true,2021-05-01,9.5
2,Bob,false,2022-11-30,7
```

the schema report includes:

```json
{
  "dialect": { "delimiter": ",", "delimiter_name": "comma", "quote_char": "\"", "has_header": true },
  "row_count": 2,
  "column_count": 5,
  "columns": [
    { "name": "id",     "type": "int",    "nullable": false, "non_empty": 2, "missing": 0, "unique": 2 },
    { "name": "name",   "type": "string", "nullable": false, "non_empty": 2, "missing": 0, "unique": 2 },
    { "name": "active", "type": "bool",   "nullable": false, "non_empty": 2, "missing": 0, "unique": 2 },
    { "name": "joined", "type": "date",   "format": "YYYY-MM-DD", "nullable": false, "non_empty": 2, "missing": 0, "unique": 2 },
    { "name": "score",  "type": "float",  "nullable": false, "non_empty": 2, "missing": 0, "unique": 2 }
  ]
}
```

Choose **Records only** to get just the typed rows, or **Schema only** to skip the records.

### Limits & edge cases

- Zero-padded integers such as `007` or ZIP codes like `01234` are kept as **strings** so leading
  zeros survive.
- A column is only given a numeric/date/bool type when **every** non-null value in it matches;
  one stray value keeps the whole column a string.
- Null tokens are matched **exactly and case-sensitively** against the trimmed cell (plus the
  empty string is always null).
- Dates are validated (month/day ranges, leap years). Supported date shapes are `YYYY-MM-DD`,
  `YYYY/MM/DD`, `MM/DD/YYYY`, `DD/MM/YYYY` and the dash variants; datetimes are `YYYY-MM-DD`
  with a `T` or space separator and an optional trailing `Z`.

## FAQ

<details>
<summary>How does it pick the delimiter?</summary>

With **Delimiter** set to *Auto-detect*, it parses the text once with each candidate (comma,
semicolon, tab, pipe) and keeps the one that produces the most consistent column count across
rows, requiring at least two columns. Set a specific delimiter to skip sniffing.

</details>

<details>
<summary>How does header detection work?</summary>

In *Auto-detect* mode it compares the first row against the inferred type of each column's data
rows: if the data is clearly typed (numbers, dates, booleans) but the first row's cell is text, it
votes that the first row is a header. An all-text table can't be told apart, so it assumes a header
is present. Force the behaviour with **Header row → First row is a header** or **No header**.

</details>

<details>
<summary>Why is my number column showing up as a string?</summary>

Every value in the column has to parse for the column to take that type. A single non-numeric
cell, a stray label, a thousands separator like `1,000`, or a leading-zero code such as `007` will
keep the column as `string`. Add unusual missing-value markers to **Null tokens** so they don't
block inference.

</details>

<details>
<summary>What counts as a missing value?</summary>

An empty cell is always treated as missing, plus any token you list in **Null tokens**
(default `NA,N/A,NULL,null,None,nan`). Missing cells become `null` in the records and are excluded
from type inference; the `missing` count and `nullable` flag in the schema reflect them.

</details>

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

No. The tool is compiled to WebAssembly and runs entirely in your browser tab — the CSV you paste
never leaves your machine.

</details>

## Related tools

- [CSV ⇄ JSON Converter](https://gizza.ai/tools/csv-json-convert/): Convert CSV to JSON or JSON to CSV in your browser — auto-detects direction, infers types, handles quoted fields and custom delimiters. Free, no upload.
- [Data Format Converter](https://gizza.ai/tools/data-format-converter/): Convert data between CSV, TSV, JSON, and NDJSON (JSONL) in any direction — auto-detects the source, infers types, unions keys. Free, in-browser, no upload.
- [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.
- [CAMT.053 Statement Parser](https://gizza.ai/tools/camt053-parse/): Parse a camt.053 (or camt.052/054) ISO 20022 bank statement XML into JSON or CSV in your browser: balances, dates, counterparties, references. No upload.
