Labs · Chat shot

Stop stitching ten screenshots.
Drop the chat log, get one clean image.

A tavern .jsonl or a quick paste, the message range worth showing, a theme, avatars — out comes a typeset long image with real bubbles, action italics and dialogue coloring. Long chats split into numbered pages and download as one zip. Nothing you drop here leaves your browser.

Freeruns in your browseryour chat never leaves it

An original demo — a lighthouse, 13 messages. Characters and plot are ours, so style away.

Everything renders in your browser — the chat is never uploaded or stored. Refresh and it's gone.

Feed it a chat first: the sample, a tavern .jsonl, or a quick paste.

Where this tool comes from

The layout engine draws on canvas instead of screenshotting DOM — DOM-capture libraries fall apart across browsers on fonts, emoji and shadows, and they still hit the same canvas height ceiling. Here line breaking (CJK breaks per character, Latin at word boundaries, unbreakable runs hard-split), bubble geometry, grouping of consecutive turns and pagination are all computed: pages cut at message boundaries first, falling back to line boundaries only when one message is taller than a whole page. The engine ships with 86 Node self-tests covering parsing, wrapping, pagination and the zip writer.

The .jsonl reading matches the tavern export shape (line 0 metadata, is_system rows skipped, mes carrying the currently-selected swipe) — the same reading our context-window lens uses. Timestamps accept ISO strings, epoch numbers and the tavern's humanized format; anything unparseable simply isn't shown rather than being invented.

What it can't do

It doesn't render HTML or Markdown rich text — beautified-card HTML output is typeset as plain text. That's WebView territory; a share image keeps the words themselves.

Swipes: only the currently selected swipe of each message is used. Hidden (is_system) rows and image attachments don't enter the picture.

Fonts come from the system stack, so glyphs differ slightly across devices (PingFang on iOS, Noto/YaHei elsewhere). Pixel-identical output would require embedding font files — not something a free local tool should ship.

FAQ

What chat formats does it accept?

Two: SillyTavern chat exports (.jsonl — one JSON object per line, metadata on line 0; Foreverse exports the same format), and plain text where each turn starts with "Name: text" on its own line. Lines without a name prefix join the previous message, so multi-paragraph turns paste fine. After parsing you pick which speaker is you, and which slice of messages to show.

Does my chat get uploaded anywhere?

No. Parsing, layout and rendering all run in your browser — this page has no upload endpoint, and the export is written straight from a local canvas to your downloads. Refresh and everything is gone. That's also why a huge log renders fast: no bytes cross the network.

Why did my long chat come out as several images in a zip?

Browsers cap canvas height (commonly 16,384px — beyond it, drawing silently produces a blank). The tool keeps every page safely under that cap, cuts at message boundaries so no bubble is split mid-thought unless a single message is taller than a whole page, numbers each page, and packs them into one zip. Short chats export as a single PNG.

How are *actions* and "dialogue" colored?

Following tavern rendering conventions: text between asterisks becomes muted italics (actions), quoted speech — straight, curly or CJK corner quotes — gets the accent color, and plain narration stays in the body color. Every theme follows the same rules; the custom theme only swaps the palette, not the logic.

Related tools & reading

← All free tools

Chat Log to Image — Turn a Roleplay Export into One Clean Share Picture · Foreverse · Xinmeng