Notes · Sep 5, 2026

# Kibana Discover CSV export: the message column is JSON

Share → CSV in Discover gives you a spreadsheet of log lines. The interesting column is the one the spreadsheet cannot open.

## What the export looks like

The header carries Elastic Common Schema names — @timestamp, log.level, service.name, host.name, trace.id, message. Every row is one document. When the service logged structured JSON, the message cell holds that JSON as a string, and because the cell is quoted, every quote inside it is doubled: "{""event"":""stripe.charge.completed""}". A spreadsheet shows the doubled quotes and stops there.

```
"@timestamp",log.level,service.name,host.name,trace.id,message
"2026-04-21T14:32:08.412Z",INFO,checkout-api,ip-10-0-3-17,4bf92f3577b34da6a3ce929d0e0e4736,"{""event"":""stripe.charge.completed"",""amount"":17054,""currency"":""usd"",""order_id"":""ord_8f3aa19c4d""}"
"2026-04-21T14:32:07.940Z",WARN,checkout-api,ip-10-0-3-17,4bf92f3577b34da6a3ce929d0e0e4736,retry.scheduled attempt=2 backoff=400ms
"2026-04-21T14:32:07.813Z",ERROR,checkout-api,ip-10-0-3-17,9c02fe13a1d04b7e8c6f2e1d0b3a5c47,"stripe.webhook.signature_invalid: no signatures found matching the expected signature for payload"
"2026-04-21T14:32:07.512Z",INFO,checkout-api,ip-10-0-3-17,08bb31f7c2a94d1e9f6b3a8d5e2c7f10,"{""event"":""cart.items.priced"",""items"":2,""total"":14900}"
"2026-04-21T14:32:06.301Z",INFO,auth-svc,ip-10-0-5-42,51e8cc02d7f34a6b8e1c9d2f3a4b5c6d,session.token.issued ttl=3600
"2026-04-21T14:32:05.087Z",ERROR,inventory,ip-10-0-7-09,f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6,"{""event"":""inventory.hold.failed"",""sku"":""BRD-OAK-002"",""reason"":""insufficient_stock"",""requested"":1,""available"":0}"
```

## Reading it as rows

Pasted or dropped, the export is detected as CSV and asks its reading question — separator, header row — with a preview beside the lines. Read as rows opens 6 rows; the @timestamp and log.level columns are recognised as the time and the level, so the level chips count INFO, WARN and ERROR the way they would over a raw log.

The message column is where the export earns the trip: 3 of its 6 cells parse as JSON, and each shows Unpack. Opened, the cell reads as nested rows in the panel — event, amount, currency, order_id — while the table keeps the string the file wrote. Filter still works on the whole row (field=value, /regex/, the level chips), and Convert writes the rows out as JSON, NDJSON or a Markdown table.

## The other Kibana paste

Not every Kibana copy is an export. Selecting rows in the Discover table and copying gives text: the time in Kibana’s own display format — Apr 21, 2026 @ 14:32:08.412 — then the columns separated by runs of spaces. That is a raw log to the engine, and it has a pattern written for exactly this paste (“Kibana Discover · copied rows”), so it reads as records without a regex from you.

```
Apr 21, 2026 @ 14:32:08.412  info  checkout-api  stripe.charge.completed amount=17054 order_id=ord_8f3aa19c4d
Apr 21, 2026 @ 14:32:07.940  warn  checkout-api  retry.scheduled attempt=2 backoff=400ms
Apr 21, 2026 @ 14:32:07.813  error  checkout-api  stripe.webhook.signature_invalid
Apr 21, 2026 @ 14:32:07.512  info  checkout-api  cart.items.priced items=2 total=14900
…
```

## Try it

## Try it on the file that broke your afternoon.

free while in alpha · no signup

---

Canonical: https://unstringify.com/notes/kibana-export-message-column
