How to switch from ChatGPT to Claude
And bring your history with you
If you’ve been using ChatGPT for a while, you’ve probably built up quite an archive of conversations. I had almost 700, some of them arranged into projects, some not. Switching to Claude doesn’t mean losing all of that. This guide is based on what I did after initially asking Claude how to do it.
Step 1: Export your ChatGPT history
In ChatGPT, go to Settings → Data Controls → Export Data
Request the export — you’ll receive an email with a download link. I had to wait a few hours for mine.
Click the download link. You need to click it within 24 hours of receiving it. It should download a zip file which, if it doesn’t unzip automatically, you’ll need to click to unzip. You’ll then have a folder with a name consisting of a long string of numbers and letters.
The export contains several files. The ones you need are the numbered JSON files: conversations-000.json, conversations-001.json, and so on. These will typically contain about a hundred coversations each so for my almost 700 conversations there were seven of them.
Step 2: Install Python
The next steps use Python scripts to process your export files. If you’ve never used Python before, here’s how to set it up.
Check if you already have Python:
On Mac: Open Terminal (search for it in Spotlight) and type
python3 --versionthen press Enter. If you see a version number, you’re good.On Windows: Open Command Prompt (search for “cmd”) and type
python --versionthen press Enter.
If you don’t have Python installed:
Go to python.org/downloads and download the latest version
Run the installer — on Windows, make sure to tick “Add Python to PATH” before clicking Install
Once installed, confirm it worked by running
python --versionagain in a new terminal window
A note on terminals: All the commands in this guide are run in a terminal (Mac) or Command Prompt/PowerShell (Windows). To navigate to a folder, use the cd command — for example, cd Downloads/chatgpt-export. You can also usually right-click a folder and choose “Open in Terminal” or “Open PowerShell here”.
Step 3: Identify your projects
ChatGPT exports don’t include project names directly, but they do include a gizmo_id field that maps to your ChatGPT projects. This script will show you what projects you have and how many conversations are in each. Save it in your ChatGPT export folder as something like get-projects.py and in a terminal do python get-projects.py to run it.
import json, glob
from collections import defaultdict
INPUT_DIR = "." # folder containing conversations-*.json files
groups = defaultdict(list)
for filepath in sorted(glob.glob(f"{INPUT_DIR}/conversations-*.json")):
for conv in json.load(open(filepath)):
gid = conv.get("gizmo_id") or "none"
groups[gid].append(conv.get("title", "Untitled"))
for gid, titles in sorted(groups.items(), key=lambda x: -len(x[1])):
print(f"\n{gid} ({len(titles)} convs):")
for t in titles[:5]:
print(f" - {t}")
The output will look something like:
none (250 convs):
- Some random conversation
- Another one-off topic
...
g-p-67ae1f1ab80081918293cb5cb1caf506 (140 convs):
- Job application help
- Cover letter draft
...
The none group contains conversations that weren’t in any ChatGPT project. The g-p-... ids are your ChatGPT project identifiers. From the first five titles of each group, you should be able to tell what each project was about, assuming your chats have descriptive titles. If they don’t, it may be worth giving the most recent chats in each ChatGPT project a good title before you run the export.
Make a note of your mapping, mapping each project id to the project name. For example:
none→ Generalg-p-67ae1f...→ Career & Job Searchg-p-67efec...→ Web Development(and so on for each ID)
You don’t have to use the exact same project names you had in ChatGPT.
Step 4: Convert conversations to markdown
This script converts all your conversations into individual markdown files, organised into folders by project. Markdown files are specially formatted files that Claude uses to tell it about a project. Edit this Python script, putting in your own project ids and names you got in Step 3, then save it in the same directory as your conversations-*.json files, naming it something like convert-convos.py, and run it in a terminal with the command python convert-convos.py.
import json, os, glob
from datetime import datetime
INPUT_DIR = "." # folder containing conversations-*.json
OUTPUT_DIR = "./claude_projects"
# Edit this mapping to match your own projects
# Keys are gizmo_id values from Step 2; values are your chosen folder/project names
PROJECTS = {
None: "General",
"g-p-REPLACE_WITH_YOUR_ID": "Your Project Name",
# add more entries here...
}
def extract_text(content):
parts = content.get("parts", []) if content else []
out = []
for p in parts:
if isinstance(p, str):
out.append(p)
elif isinstance(p, dict):
if p.get("content_type", "").startswith("image"):
out.append("[image]")
elif p.get("name"):
out.append(f"[file: {p['name']}]")
return "\n".join(out)
def get_messages(mapping):
root = next((k for k, v in mapping.items() if not v.get("parent")), None)
if not root:
return []
messages, node_id, visited = [], root, set()
while node_id and node_id not in visited:
visited.add(node_id)
node = mapping.get(node_id, {})
msg = node.get("message")
if msg:
role = msg.get("author", {}).get("role", "")
text = extract_text(msg.get("content", {}))
if role in ("user", "assistant") and text.strip():
messages.append((role, text.strip()))
kids = node.get("children", [])
node_id = kids[0] if kids else None
return messages
# Create output folders
for name in PROJECTS.values():
os.makedirs(f"{OUTPUT_DIR}/{name}", exist_ok=True)
# Load all conversations
convs = []
for f in sorted(glob.glob(f"{INPUT_DIR}/conversations-*.json")):
convs.extend(json.load(open(f)))
print(f"Processing {len(convs)} conversations...")
for conv in convs:
title = conv.get("title") or "Untitled"
ts = conv.get("create_time")
date = datetime.fromtimestamp(ts).strftime("%Y-%m-%d") if ts else "unknown"
messages = get_messages(conv.get("mapping", {}))
if not messages:
continue
gid = conv.get("gizmo_id")
folder = PROJECTS.get(gid, "General")
safe = "".join(c if c.isalnum() or c in " -_" else "_" for c in title)[:80].strip()
with open(f"{OUTPUT_DIR}/{folder}/{date} {safe}.md", "w") as f:
f.write(f"# {title}\n*{date}*\n\n")
for role, text in messages:
label = "**You**" if role == "user" else "**ChatGPT**"
f.write(f"### {label}\n{text}\n\n")
print(f"Done → {OUTPUT_DIR}/")
After running it, you’ll have a claude_projects/ folder containing one subfolder per project, each containing individual .md files named by date and conversation title.
Step 5: Create projects in Claude
Login to claude.ai and click Projects in the sidebar
Create a new project for each folder you generated in Step 4
Give each project the same name as the corresponding folder
Step 6: Upload files to each project
For each project:
Open the project in Claude
Scroll down to the Files section and click the + button
Choose Upload from device
Select all the files from the corresponding folder (Ctrl+A / Cmd+A to select all)
Click Open and wait for indexing to complete
A few things to expect:
Indexing time scales with the number of files. A large project (100+ files) can take 30–60 minutes to fully index. If the interface appears stuck, refresh the page — the files are usually already indexed.
Capacity: each project shows a capacity indicator. Smaller, focused projects use very little capacity; large general-purpose projects with 200+ files will use more. If you hit the limit, consider splitting large projects or filtering out less relevant conversations before uploading.
Duplicates: if two conversations have the same title and date, the OS file picker will silently skip one. This is normal and affects only a handful of files at most.
What you get
Once uploaded, Claude can reference any of your past conversations within a project. When you start a new chat inside a project and ask something like “have I looked at this before?” or “what did I decide about X?”, Claude will search the project knowledge and surface relevant context from your ChatGPT history.
It’s not a perfect recreation of having a continuous memory — Claude treats the files as reference documents rather than conversations that actually happened within Claude — but it’s a practical way to carry your accumulated knowledge across platforms without starting from scratch.
Tips
Be selective with General — the uncategorised conversations pile up over time and many will be trivial. Consider skimming the folder and deleting one-off conversations (e.g. “what’s the weather like in X”) before uploading, to keep the project focused.
Add project instructions — each Claude project has an Instructions field. Use it to tell Claude the context of the project, e.g. “This project contains my history of web development conversations. I primarily work with PHP, JavaScript and Python.” This helps Claude interpret the files more accurately.
The files stay editable — you can delete individual files from a project at any time, so don’t worry too much about uploading everything initially.
Alternative methods
This is not the only way of doing this but it’s the one that worked for me. Here’s an alternative method, perhaps a bit simpler, from YouTuber Eliot Prince:


