Claude Chat Exporter
A privacy-first tool that exports your Claude.ai conversations to clean Markdown. It runs entirely in your browser — no server of its own, nothing uploaded, no tracking.
Everything comes through — tables, math and code at full fidelity, plus artifacts, created files, charts and attachments — all read directly from Claude's own API. Exports carry YAML frontmatter with one heading per turn, so they drop straight into an Obsidian vault or a RAG pipeline.
Claude's internal API changes without notice, and someone has to keep up.
Sponsoring this project is what keeps it maintained. More →
⚡ One-Click Export (Bookmarklet)
The easiest way — no console, no copy-paste, works for non-developers too:
- Open the one-click install page »
- Drag the “📥 Claude Export” button onto your browser's bookmarks bar.
- Open any conversation on claude.ai and click the bookmark — your
.mdfile downloads automatically.
The bookmarklet is just this repository's open-source script wrapped into a link. It runs entirely in your browser — the tool has no server of its own, the only network call for your conversation is to Claude's own backend, and it stores nothing. The bookmarklet also checks for updates and shows an “update available” notice when a newer version is published, so you can re-drag to grab the latest.
Prefer to run it yourself? See Usage (Console) below.
Features
- 🎯 Perfect Markdown Fidelity - Reads Claude's own source markdown from its API — no HTML parsing, no conversion. The result is a clean, faithful document that reads beautifully on its own
- 📈 Complete Element Support - Tables, math, code, lists, complex formatting — everything, byte-perfect
- 🧩 Artifacts, Files & Widgets - Artifacts (their final version), created files, and charts/diagrams are exported as clean fenced code blocks, in place and in order
- 📎 Attachments - Uploaded images embedded, documents linked, and text files inlined — exports stay self-contained
- 🗂️ Obsidian- & RAG-ready - YAML frontmatter + one heading per turn means it drops straight into an Obsidian vault or an AI/RAG pipeline — not just a plain dump (more below)
- 📊 Complete & In Order - Every message on the current branch, correctly ordered — even in long conversations that only partly render on screen
- 🕐 Timestamps - Per-message timestamps for both human and Claude turns, from Claude's API
- 🔒 Private by Design - No servers, no tracking; runs in your browser and only ever calls Claude's own backend, over your existing session
- 📁 Smart Filename Generation - Uses the actual conversation title from the API
- 🛡️ Robust to UI Changes - Reads a stable data contract, not fragile CSS selectors
How It Works
It's a single fetch, transformed into markdown:
- Fetch - Calls Claude's internal API for the current conversation (
/api/organizations/{orgId}/chat_conversations/{conversationId}), authenticated by your existing session cookie. The response contains the title and every message. - Order - Reconstructs the conversation's current branch by walking the message tree from the current leaf up its parent chain (so a regenerated response exports exactly what's on screen).
- Extract - Walks each message's content blocks in order:
textblocks (Claude's original source markdown) plus special elements — artifacts, created files, and charts/diagrams/widgets — rendered in position; hidden/system messages are skipped. - Output - Writes a single markdown file: YAML frontmatter (title, source, model, export date) followed by one
#-level header per turn (# Human — …/# Claude — …) so Claude's own##/###content nests correctly beneath it. The result is a clean, faithful document that reads perfectly on its own — and the same structure makes it drop-in ready for Obsidian & AI/RAG pipelines.
Branches / regenerated responses: the export follows the branch Claude is currently showing — its active leaf — not necessarily the newest one. If you've regenerated a response and want to export a different branch, switch to that version in Claude first (the
‹ ›arrows on a regenerated message), then run the exporter — the switch takes effect immediately, no page reload needed.
Why read the API instead of the page?
Claude generates markdown, and the page only ever holds a small window of a long conversation in the DOM. Copy buttons hand over that markdown faithfully — but the DOM was still needed to find each message, work out who said it, and read the conversation title, and each of those is a CSS selector waiting to break. Reading the API gets every message's source markdown directly, along with the elements no copy button can reach.
❌ Driving the page (DOM + copy buttons):
- Only sees the messages currently rendered → long chats export partially
- Pairs human and Claude turns by index → a regenerated branch can misalign them
- Reaches only what has a copy button → no artifacts, files or attachments
- Couples to CSS selectors that change constantly → a maintenance nightmare
✅ Reading Claude's API:
- Complete conversation, always, in the order it appears on screen
- Claude's original source markdown → perfect fidelity, zero conversion
- Artifacts, created files, widgets and attachments come along too
- A stable data contract instead of brittle selectors
Usage (Console)
Prefer running it yourself, or want to tweak the script? Run it straight from the browser console:
- Open your conversation with Claude in your web browser.
- Open the browser's developer console:
- Chrome/Edge: Press F12 or Ctrl+Shift+J (Windows/Linux) or Cmd+Option+J (Mac)
- Firefox: Press F12 or Ctrl+Shift+K (Windows/Linux) or Cmd+Option+K (Mac)
- Safari: Enable the Develop menu in preferences, then press Cmd+Option+C
- Copy the entire script in the file
claude-chat-exporter.jsand paste it into the console.- First time? Chrome, Edge, and Firefox block pasting into the console as a safety measure. If you see that warning, type
allow pasting, press Enter, then paste the script again. (Only needed once per browser profile — the one-click bookmarklet skips this entirely.)
- First time? Chrome, Edge, and Firefox block pasting into the console as a safety measure. If you see that warning, type
- Press Enter to run the script.
- The script shows a small status indicator and automatically downloads a file named
{conversation-title}.md(conversation-titlebeing the Claude conversation title from the API).
Complete Element Support
Because this reads Claude's source markdown directly, it automatically handles:
- ✅ Tables - Perfect markdown table formatting
- ✅ Math - LaTeX and inline math notation
- ✅ Code blocks - With proper language detection
- ✅ Lists - Nested lists with correct formatting
- ✅ Links - All link types and formats
- ✅ Formatting - Bold, italic, strikethrough, etc.
- ✅ Blockquotes - Proper quote formatting
- ✅ Headers - All heading levels
- ✅ Artifacts - Exported as a labelled fenced code block (final version), in place
- ✅ Created files -
create_fileoutputs, as a fenced code block with the filename - ✅ Charts / diagrams / widgets -
visualizewidgets exported as code (mermaid renders natively in Obsidian) - ✅ Attachments - Images embedded, documents linked, text files inlined
- ✅ Future elements - Automatically supported
File Output
- Filename:
{conversation-title}.md(from the API title, elseclaude_conversation) - Format: YAML frontmatter +
#-per-turn headers; bodies are Claude's own source markdown - Content: Complete conversation, in order, with per-message timestamps and inlined text-attachment content
- Encoding: UTF-8 with standard line endings
Example Output
YAML frontmatter carries document metadata; each turn is an # header so Claude's own ##/### headings nest beneath it. Attachments render above the text (text attachments are blockquoted, label and all); artifacts, created files, and widgets render in place as labelled fenced code blocks:
---
title: "Sorting algorithm comparison"
source: "https://claude.ai/chat/…"
model: "claude-opus-4-…"
exported: 2026-02-23
---
## Human — Feb 23, 2026, 10:30 AM
> **Attachment: requirements.md · text/markdown · 1.2 KB**
>
> # Requirements
> Compare the common sorting algorithms in a table.
Can you create a comparison table, and a small React widget to visualise it?
## Claude — Feb