How to export a ChatGPT conversation to Markdown
How to save a ChatGPT chat as Markdown: by hand, with a script over the official export, or with a button in Chatsavo — with Obsidian front matter.
Markdown is the best format for AI chats: any editor reads it, code blocks keep their language, tables stay tables, and Obsidian, Notion and GitHub understand it without conversion. ChatGPT still has no "Save as Markdown" button. Here are two working ways to export a ChatGPT chat — by hand and with a script — plus how to download a chat as Markdown from Chatsavo.
What ChatGPT does on its own
As of October 2026, ChatGPT has two built-in ways to get a conversation out:
| Method | What you get | Good for |
|---|---|---|
| "Copy" button under a reply | One reply's text as Markdown | One or two replies |
| Settings → Data controls → Export data | A ZIP with conversations.json and chat.html for your whole history |
Backups, bulk processing |
The official export arrives by email. It can take up to 7 days to prepare, and the link is valid for 24 hours (OpenAI Help). It's available on Free, Go, Plus and Pro, but not in Business or Enterprise workspaces. There are no Markdown files in the archive — just JSON and HTML (ChatGPT Exporter, as of October 2026).
Method 1. By hand, for one short chat
- Hover over a ChatGPT message and click Copy. The reply is copied with its Markdown: headings, lists and code blocks.
- Paste it into your editor (VS Code, Obsidian, Typora).
- Copy your own questions separately and mark them, say, as
### You.
This works for five or six messages. On a long chat you'll spend more time stitching than reading.
Method 2. From the official export with a script
To convert your entire history to Markdown, take conversations.json from the archive and run it through a script. The file's structure is internal and may change, but as of October 2026 each chat has a title, a create_time and a message tree called mapping.
A minimal Python script: one file per chat, roles labeled, branches flattened into a sequence.
import json, re, pathlib, datetime
data = json.load(open("conversations.json", encoding="utf-8"))
out = pathlib.Path("chatgpt-md"); out.mkdir(exist_ok=True)
for conv in data:
title = conv.get("title") or "Untitled"
nodes = conv.get("mapping", {}).values()
msgs = [n["message"] for n in nodes if n.get("message")]
msgs.sort(key=lambda m: m.get("create_time") or 0)
lines = [f"# {title}", ""]
for m in msgs:
role = m["author"]["role"]
parts = [p for p in m.get("content", {}).get("parts", []) if isinstance(p, str)]
text = "\n".join(parts).strip()
if role not in ("user", "assistant") or not text:
continue
lines += ["### You" if role == "user" else "### ChatGPT", "", text, ""]
date = datetime.date.fromtimestamp(conv.get("create_time") or 0)
name = re.sub(r'[\\/:*?"<>|]+', " ", title)[:80].strip()
(out / f"{date} {name}.md").write_text("\n".join(lines), encoding="utf-8")
Limits of this approach:
- it's a snapshot: new chats mean a new export;
- branches: if you edited questions,
mappingkeeps every version, and sorting by time will interleave them. To keep only the active branch, walk fromcurrent_nodeup to the root viaparent; - images and files come separately or as links, and you'll have to place them by hand.
For a one-off archive of your whole history, it's the best free route.
Export in Chatsavo
Chatsavo downloads a chat as Markdown right from the panel:
- one chat — the chat's "…" menu in the panel → "Download Markdown";
- several chats — press "Select" on the panel, tick the chats and press "Download Markdown": they come as one file;
- 20 recent chats for Obsidian — in the extension settings, "Bookmarks and Markdown" → "Download 20 recent chats as Markdown".
The file holds the text Chatsavo saved when you opened the chat. If you haven't opened a chat since installing, the file has no text for it: open the chat and wait a second. The file downloads to your computer; nothing goes to our servers.
What the file looks like:
- it starts with the chat title and a line with the site, date and a link to the original chat;
- roles are labeled "You" and "AI".
The Obsidian download uses YAML front matter instead of that line:
---
title: "Migrating to Postgres 17"
source: "ChatGPT"
url: "https://chatgpt.com/c/…"
created: 2026-09-14
updated: 2026-10-02
folder: "Work / Backend"
tags: []
---
# Migrating to Postgres 17
### You
Which pg_upgrade changes should I check?
### AI
…
folder comes from your Chatsavo folder and tags from the chat's tags, so Obsidian search and Dataview work on them right away.
Besides Markdown, there's a full JSON download of all your Chatsavo data: Settings → Your data → "Download everything (JSON)". Files up to 25 MB are restorable in this version; larger downloads are export-only for now. Changes are listed in the changelog.
Which method to pick
- One reply → ChatGPT's Copy button.
- Your whole history, once → official export plus a script.
- Regularly saving individual chats to Obsidian or Notion → "Download Markdown" in Chatsavo, or the Copy button.
Where to keep exported chats
A file on its own isn't worth much; what matters is finding it later. A few setups that work:
- Obsidian. A dedicated
AI/folder in your vault with topic subfolders. Front matter fields let Dataview build a table: every chat in "Work / Backend" for the month. - Notion. Markdown import creates a page per file. Handy for teams: a chat becomes a document people can comment on.
- Your project's Git repo. A
docs/decisions/folder with the conversations where architecture decisions were made. A year later, it beats anyone's memory.
Start file names with a date — 2026-10-02 Migrating to Postgres 17 (ChatGPT).md — so sorting by name matches chronology.
Common problems
Code blocks lost their language. That happens when you copy by selecting with the mouse: the browser copies rendered text, not the source markup. Use the Copy button under the message, or the official export.
A table turned into tab-separated text. Same cause. The Copy button keeps tables in Markdown syntax.
A long file name won't save. Chat titles can be long and contain / or :. The script above trims the name to 80 characters and replaces illegal characters; do the same in yours.
Markdown and Obsidian export, folders and full-text search for ChatGPT and Claude work in Chatsavo today — free, no card. How to install Chatsavo.
Find any old chat in a second
Chatsavo adds folders and full-text search to ChatGPT and Claude. Free, and chat text stays in your browser.