/api/convert/json-to-csv
MCP tool json_to_csv Parses input strictly as JSON. An array of objects becomes one row per object, with a header made of every key in first-seen order (a missing key gives an empty cell); a single object becomes one row. An array of arrays becomes one row per array, with no header. Strings are written as they are, numbers exactly as written in the JSON (1.0 and 20-digit integers survive), booleans as true/false, null as an empty cell, and nested objects or arrays as compact JSON text (listed in notes). Values are quoted per quoting.
Browser version (runs locally): CSV Validate & Format.
Try it
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
input required | string (≤ 200000 chars) | — | The JSON text: an array of objects, an array of arrays, or one object. Send it as a string field or as a raw text/plain POST body. |
delimiter | comma | semicolon | tab | pipe | comma | Delimiter for the output: comma, semicolon, tab or pipe. |
header | boolean | true | Write the header row (arrays of objects only). |
quoting | minimal | all | nonnumeric | minimal | minimal quotes only values that need it (a delimiter, quote or line break, or leading/trailing whitespace); all quotes every value; nonnumeric quotes everything except numbers. |
line_ending | lf | crlf | lf | Line break written after every row. crlf is what RFC 4180 specifies; lf is what most tools write, and every reader accepts both. |
Also accepted on every endpoint: format (json | text).
Parameters may come from the query string, a JSON object body, an urlencoded or multipart form,
or (for input) a text/plain body.
Global parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
format | json | text | json | json returns the documented object. text returns only the primary value as text/plain (see "Text output"). |
Response 200 application/json
| Field | Type | Description |
|---|---|---|
csv | string | The CSV text, ending with a line break (empty for an empty array). |
header | array of string | null | The header row; null when there is none. |
rowCount | integer | Data rows written. |
columnCount | integer | Columns (the longest row, for arrays of arrays). |
notes | array of string | What was adapted: nested values written as JSON, missing keys, ragged arrays. |
Text output (format=text, text/plain): The CSV text.
Errors
Errors are JSON: {"error": "<message>", "code": "<code>", "param": "<name>"?}.
| Status | Code | When |
|---|---|---|
422 | unprocessable_input | input is not valid JSON (line and column given), or is not an array of objects, an array of arrays, or an object. |
400 | invalid_parameter | input is longer than 200,000 characters, or an option is not a listed value. |
400 | missing_parameter | A required parameter is absent. |
400 | unknown_parameter | A parameter name is not in the table above (typos are rejected, not ignored). |
413 | payload_too_large | The request body exceeds 1 MiB. |
405 | method_not_allowed | A method other than GET, POST or OPTIONS. |
Behaviour
- Idempotent: the same arguments always return the same result.
-
Requires a client ID and secret (authentication). Each call is
recorded as one metadata row against your client ID; inputs and outputs are never stored or
logged. Responses carry
cache-control: no-store. - CORS: any origin may call this endpoint from a browser, using your credentials.
Examples
Responses below were produced by running each request through this code at build time. Long strings are shortened.
Objects with different keys and a nested value
curl -X POST 'https://util.caruana.me/api/convert/json-to-csv' \
-H 'content-type: application/json' \
-d '{"input":"[{\"id\":1,\"name\":\"Widget, large\",\"price\":9.99},{\"id\":2,\"name\":\"Say \\\"hi\\\"\",\"tags\":[\"a\",\"b\"]},{\"id\":12345678901234567890,\"name\":null}]"}'
Response 200
{
"csv": "id,name,price,tags\n1,\"Widget, large\",9.99,\n2,\"Say \"\"hi\"\"\",,\"[\"\"a\"\",\"\"b\"\"]\"\n12345678901234567890,,,\n",
"header": [
"id",
"name",
"price",
"tags"
],
"rowCount": 3,
"columnCount": 4,
"notes": [
"3 objects lack some keys; those cells are empty.",
"Nested objects or arrays were written as JSON text in column tags."
]
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "json_to_csv",
"arguments": {
"input": "[{\"id\":1,\"name\":\"Widget, large\",\"price\":9.99},{\"id\":2,\"name\":\"Say \\\"hi\\\"\",\"tags\":[\"a\",\"b\"]},{\"id\":12345678901234567890,\"name\":null}]"
}
}
}Arrays to semicolon-separated CSV with CRLF
curl -X POST 'https://util.caruana.me/api/convert/json-to-csv' \
-H 'content-type: application/json' \
-d '{"input":"[[\"x\",\"y\"],[1,2],[3,4]]","delimiter":"semicolon","line_ending":"crlf"}'
Response 200
{
"csv": "x;y\r\n1;2\r\n3;4\r\n",
"header": null,
"rowCount": 3,
"columnCount": 2,
"notes": []
}
Same call as an MCP tools/call
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "json_to_csv",
"arguments": {
"input": "[[\"x\",\"y\"],[1,2],[3,4]]",
"delimiter": "semicolon",
"line_ending": "crlf"
}
}
}