Export Gemini Conversations to Markdown Before Google Deletes Them: A 2026 Guide
Short answer: Google Takeout is the only official, complete export path for Gemini conversations, and it gives you HTML or JSON, not Markdown. So the
NexaSphere Team
Author

Short answer: Google Takeout is the only official, complete export path for Gemini conversations, and it gives you HTML or JSON, not Markdown. So the working recipe is: request a Takeout archive of your Gemini Apps Activity, then convert it locally with a small script. If you need something faster for a handful of chats, copy the raw response text out of the UI and paste it into a .md file. Everything else (browser extensions, third-party "chat exporters") means handing your conversation history to someone you have no relationship with.
The deletion pressure is real, but it is not a countdown clock. Google applies an auto-delete window to Gemini Apps Activity by default, and conversations age out of your history once that window passes. You can change the retention setting, and you should check what yours is set to before you assume anything is safe. The point of exporting is that you stop depending on a setting you do not control.
Check your retention setting first
Before exporting anything, go to your Google Account activity controls and find Gemini Apps Activity. Two things matter there:
- Whether activity saving is on. If it is off, recent conversations may still be retained for a short period for service and safety reasons, but they are not in your long-term history and will not show up in a full archive the way saved activity does.
- The auto-delete window. Google offers a set of retention choices. Whatever yours is set to, that is the horizon on your oldest conversations.
Write down what you find. It determines whether this is a one-time cleanup or something you should schedule.
Request the Takeout archive
Go to takeout.google.com, deselect everything, then select only the Gemini product entry. Selecting everything produces a giant archive you will wait days for.
A few settings worth getting right:
- Format. Takeout typically offers HTML and JSON for activity-style data. Take JSON if it is offered. HTML is readable but you will fight the markup during conversion. JSON is structured and converts cleanly.
- Delivery. Email download link is fine for most people. If the archive is large, sending it to Drive avoids link expiry problems.
- Archive size. Set a split size that your machine can actually unzip. Splitting is better than one file that fails at 96%.
Export time varies with how much history you have. Small archives can arrive in minutes; large ones take much longer. Google emails you when it is ready. Download links expire, so grab it promptly.
Understand what you actually got
Unzip the archive and look at the structure before writing any code. You are looking for the Gemini directory and, inside it, the activity file. Open it and read a few records by hand.
What you are checking for:
- How prompts and responses are paired (some activity exports store them as separate records tied by timestamp rather than as a nested conversation object)
- Whether response text is stored as HTML fragments even inside a JSON file
- Whether timestamps are ISO strings or epoch values
- What is missing: uploaded files, images, and code execution output frequently do not survive an activity export intact
That last one is the honest caveat. An activity export is a record of your text exchanges. It is not a byte-perfect archive of everything you saw in the app. If a conversation's value was in an attached file, save that file separately.
Convert to Markdown
Once you know the shape of the data, conversion is short. Here is a Python starting point. Do not run it blind, adjust the field names to match what you actually saw in your archive.
import json, re, html, pathlib
from datetime import datetime
SRC = pathlib.Path("Takeout/My Activity/Gemini/MyActivity.json")
OUT = pathlib.Path("gemini-md")
OUT.mkdir(exist_ok=True)
def strip_html(s):
s = re.sub(r"<br\s*/?>", "\n", s or "")
s = re.sub(r"</?p>", "\n", s)
s = re.sub(r"<[^>]+>", "", s)
return html.unescape(s).strip()
def slug(s, n=60):
s = re.sub(r"[^a-z0-9]+", "-", (s or "untitled").lower())
return s.strip("-")[:n] or "untitled"
records = json.loads(SRC.read_text(encoding="utf-8"))
for i, r in enumerate(records):
title = strip_html(r.get("title", ""))
ts = r.get("time", "")
try:
day = datetime.fromisoformat(ts.replace("Z", "+00:00")).strftime("%Y-%m-%d")
except ValueError:
day = "undated"
body = ["---",
f'title: "{title[:80]}"',
f"date: {day}",
"source: gemini",
"---",
"",
f"## Prompt",
"",
title,
""]
for d in r.get("details", []) or []:
body.append(strip_html(json.dumps(d)))
for sub in r.get("subtitles", []) or []:
body.append(strip_html(sub.get("name", "")))
fname = OUT / f"{day}-{i:05d}-{slug(title)}.md"
fname.write_text("\n".join(body), encoding="utf-8")
print(f"wrote {len(records)} files to {OUT}")
Two things this deliberately does:
One file per conversation. Not one giant file. Per-file output is what makes the archive searchable later with ripgrep, and it drops straight into Obsidian, a static site generator, or a git repo without further work.
YAML frontmatter. Title, date, and source. This costs three lines and makes the difference between a folder of text and something you can query.
If your archive turns out to be HTML rather than JSON, swap the parsing layer for BeautifulSoup and keep the rest. The conversion logic is the easy part; understanding the record layout is the work.
Verify before you trust it
Do not skip this. After conversion:
- Compare file count against record count in the source
- Open the three longest and three shortest files and read them
- Grep for a phrase you remember from a specific conversation and confirm it lands in the right file
- Check that code blocks survived (this is where naive HTML stripping usually fails, and it fails silently)
A broken export that looks fine is worse than no export, because you will delete the original.
The fast path for a few conversations
If you only care about a handful of chats, skip all of the above. Open the conversation, select the response, copy, paste into a .md file. Gemini's responses are generated from Markdown, so what you paste often retains structure reasonably well; if the formatting collapses to plain text, you will need to re-add headings by hand.
This does not scale past a dozen or so conversations, and it is easy to convince yourself you will do it later. You will not.
Why I skip the browser extensions
There are extensions that add an "export" button to Gemini. They work. The problem is what they require: read access to the page containing every conversation you open. Extension ownership changes hands, permissions get expanded in updates you auto-accept, and your conversation history is exactly the kind of data that includes things you would not paste into a stranger's tool.
Takeout plus fifty lines of local Python has no such exposure. If you do use an extension, at least review its permissions and read its privacy policy, and prefer open-source ones you can actually inspect.
Make it a habit, not a project
One export is a snapshot that starts going stale immediately. Two low-effort options:
- Scheduled Takeout. Takeout can create exports on a recurring schedule for a period of time. Set it up once and let the archives land in Drive.
- A calendar reminder. Quarterly, run the export and the conversion script. Fifteen minutes.
The reason to do either is not that Google is going to lose your data. It is that your retention window is a setting on someone else's system, and a folder of Markdown on your own disk is not.
FAQ
Does turning off Gemini Apps Activity delete my old conversations? Turning it off stops new activity from being saved to your history. It does not necessarily purge what is already there. Export first, then change the setting, so you are not relying on a guess.
Can I export a single Gemini conversation officially? Not as a discrete file. Takeout works at the product level. For one conversation, copy and paste is the practical answer. Gemini can also export some responses to Docs, which is a different thing from an archive but useful for individual outputs.
Will my uploaded files and images be in the archive? Often not. Activity exports focus on text. If attachments mattered to a conversation, save them yourself and reference them from the Markdown file.
Is Takeout data enough to rebuild a conversation's context for another model? Usually yes for text. You get the prompts and responses in order, which is what a model needs. What you lose is anything that lived outside the text: files, tool output, and rendered artifacts.
What if my archive is HTML instead of JSON? Same approach, different parser. Use BeautifulSoup to extract the conversation blocks, then feed them into the same file-writing logic. Expect to spend more time on selectors, because the class names in an export are not a stable API.
How often should I run this? Match it to your retention window with room to spare. If your auto-delete is set to a year, quarterly is comfortable. If you have it set shorter, go monthly.
Free cheat sheet
Keep your AI chats findable
Grab The AI Conversation Organization Cheat Sheet — a 5-folder taxonomy, naming rules, a cross-platform ChatGPT/Claude/Gemini workflow, and a 5-minute weekly ritual. One PDF, set up in one sitting.