Chat Transcript Viewer
How it works
What it accepts
Four shapes cover practically every LLM log: a bare messages array [{role, content}, ...]; a full request body — {"messages": [...]} with an Anthropic-style top-level "system" prompt folded in as the first message; a single message object; or JSONL with one JSON document per line, the format of fine-tuning datasets and many agent logs. A JSONL file of {"messages": [...]} lines renders as numbered records; a JSONL stream of individual message objects is treated as one conversation.
Tool calls, results and thinking blocks
The parts that are least readable as raw JSON get explicit markers. An OpenAI assistant message with tool_calls renders each call as [tool call: name · id] with its arguments pretty-printed (they arrive as a JSON string inside JSON — double-escaped, which is exactly why reading raw logs hurts). The matching role:"tool" message renders as [tool result for id]. Anthropic's tool_use and tool_result content blocks get the same treatment, including is_error flags and nested content. Extended thinking blocks are labeled [thinking], and images show as a placeholder with their size instead of a wall of Base64.
Why not just format the JSON
A formatter keeps the structure that makes conversations unreadable: content arrays nest blocks, tool arguments are JSON-in-a-string, newlines are literal \n. A 20-turn agent session is thousands of lines formatted, but a few screens as a transcript. Formatting still has its place — for that, this site's JSON tool with its UNESCAPE mode is one click away.
Examples
| {"messages":[{"role":"user","content":"hi"}]} | ---- USER ---- hi |
| assistant message with tool_calls | [tool call: get_weather · call_1] {"city": "Paris"} |
| 3 lines of {"messages":[...]} JSONL | ==== RECORD 1..3 with per-record transcripts |
FAQ
Which formats are supported?
OpenAI Chat Completions (string content, content-part arrays, tool_calls, role "tool", refusals, legacy function_call) and Anthropic Messages (content block arrays, tool_use / tool_result, thinking, images, top-level system prompt). Plus JSONL: fine-tune files with a {"messages": [...]} object per line, or one message object per line.
Why does it say 'no messages found' on valid JSON?
The JSON parsed, but nothing shaped like a conversation was inside — it needs a messages array, an object containing one, or a single {role, content} object. A Chat Completions response, for example, keeps its message under choices[0].message: paste that object, not the whole response envelope.
Are images in the conversation shown?
They render as placeholders — [image: image/png · 84213 chars base64] or the URL — not as pictures. That keeps a vision-heavy transcript readable. To see one image, copy its Base64 into the Base64 tool's IMAGE mode.
Is it safe to paste conversations with secrets?
Yes. The page ships a strict Content-Security-Policy: connect-src 'none' blocks fetch, XHR, WebSockets and beacons, while default-src 'self' and form-action 'none' block every other way markup could send data off-site. The transcript is rendered in your browser and cannot leave it.