How to open ChatGPT conversations.json and convert it to Markdown (2026)

You requested your ChatGPT export, unzipped it, and found conversations.json: one giant file that is hard to read. Here is what is inside and how to turn it into normal notes.

1. Get the export

  1. In ChatGPT open your profile menu → Settings → Data controls.
  2. Under Export data click Export, then Confirm export.
  3. Open the email (or SMS) and click Download data export while signed in to the same account. The link expires 24 hours after it arrives, and exports can take up to 7 days.

2. What is in the ZIP

Why it looks odd: each chat stores messages as a tree (in a field called mapping), because edits and regenerations create branches. To get the thread you actually saw, you start at current_node and follow each message's parent back to the start.

3. Convert it to Markdown (free script)

Save this as convert.py in the same folder as conversations.json and run python3 convert.py. It writes one .md file per chat, with title and date frontmatter, into a chatgpt-markdown folder. It only reads files on your computer.

import json, re, pathlib, datetime

data = json.load(open("conversations.json", encoding="utf-8"))
out = pathlib.Path("chatgpt-markdown"); out.mkdir(exist_ok=True)

for c in data:
    # Each chat is a tree of messages. Walk back from the last message
    # you saw (current_node) to the root to get the visible thread.
    node, msgs = c.get("current_node"), []
    while node:
        n = c["mapping"][node]
        m = n.get("message") or {}
        parts = (m.get("content") or {}).get("parts") or []
        text = "\n".join(p for p in parts if isinstance(p, str)).strip()
        role = (m.get("author") or {}).get("role")
        if text and role in ("user", "assistant"):
            msgs.append((role, text))
        node = n.get("parent")
    msgs.reverse()

    title = c.get("title") or "Untitled"
    date = datetime.datetime.fromtimestamp(c.get("create_time") or 0).strftime("%Y-%m-%d")
    safe = re.sub(r"[^\w\- ]", "", title)[:60].strip() or "chat"
    head = f'---\ntitle: "{title.replace(chr(34), chr(39))}"\ndate: {date}\nsource: chatgpt\n---\n\n'
    body = "\n\n".join(f"**{'You' if r == 'user' else 'ChatGPT'}:**\n\n{t}" for r, t in msgs)
    (out / f"{date} {safe} {str(c.get('id', ''))[:6]}.md").write_text(head + body, encoding="utf-8")

print("done:", len(data), "chats")

Limits: it keeps text from you and ChatGPT and skips images, tool output and hidden system messages. OpenAI can change the format, so if a field is missing, open the JSON and adjust.

4. Put it in Obsidian

Drop the folder into your vault (for example AI/ChatGPT). The date and source frontmatter lets Dataview list chats by month. More tips in Export ChatGPT history to Markdown and Obsidian.

Want every chat exported at once? ThreadVault (disclosure: we make it) is a Chrome extension that bulk-exports your AI chats to Obsidian-ready Markdown plus JSON in one ZIP, processed locally in your browser. It is not on the Chrome Web Store yet: the Perplexity version is built, and ChatGPT, Claude and Gemini support is coming in version 1.1. $19 one-time for all four AI tools, with a $9 founding price for the first 50 buyers.
See ThreadVault or join the free waitlist

Related guides

Not affiliated with OpenAI. Export steps are from OpenAI's help center. Last checked October 27, 2026; features change, so verify in the app. Questions or corrections: hello@loomwise.app.