Topic: gemini conversation export

Gemini Conversation Export — How to Get Your Google Gemini Chats Out (2026)

Google Gemini does not ship an in-app export. The only path is Google Takeout, and what comes back is HTML, not JSON — a meaningful step backward from what ChatGPT and Claude offer. Here's the request flow, what's missing, and the parsing recipes that make the archive usable.

TL;DR

Go to takeout.google.com → click Deselect all → scroll to My Activity → click All activity data included → deselect everything except Gemini Apps → click OK → choose HTML as the format → request a one-time export. Google emails a download link 4–48 hours later (longer than ChatGPT or Claude, which deliver in minutes). The archive is a directory containing one MyActivity.html file (or several, split by month) with prompts and responses interleaved as flat <div> entries. No JSON, no per-conversation grouping, no Gem configurations. Use the 30-line parsing script below to convert it to a JSON-shaped conversations.json the same loaders that handle ChatGPT exports and Claude exports can read.

Why this guide is shorter on glamour and longer on workarounds

If you came here from how to export your ChatGPT history or how to export your Claude conversations expecting a similar in-app button and a clean JSON file, the honest answer is: that's not what Google ships. Gemini's export story is a deliberate Google decision — the chat history is treated as an activity log, like Search and Maps and YouTube comments, rather than as a first-class application surface like Gmail (which exports as MBOX) or Drive (which exports as native file types). The result is that everything downstream — archiving, search, decision extraction — has an extra parsing step compared to the JSON-emitting platforms.

This page exists because the chat-history extraction cluster on whychose.com covers ChatGPT and Claude in depth (12 pages between them) and was missing the third platform that senior engineers actually use. Senior engineers who treat Gemini as a thinking partner — typically for Google Workspace integration, Vertex AI prototyping, or for the long-context use cases Gemini 2.5 handles well — get less back from the export than they got out of ChatGPT or Claude. Knowing the gap up front lets you plan around it.

How to request the export — the exact path

  1. Open takeout.google.com in a browser. Sign in with the Google account whose Gemini history you want. If you used Gemini under both a personal account and a Workspace account, you have to request separate exports for each account.
  2. Click "Deselect all." The default Takeout configuration includes 50+ products; selecting them all makes the export take days and ship 30+ GB of data you don't want.
  3. Scroll to "My Activity" in the product list and check it.
  4. Click "All activity data included" (the link below the My Activity checkbox). A modal appears listing every product whose activity is bundled.
  5. Click "Deselect all" inside the modal, then check only Gemini Apps. (Do not also check "Search" or "Maps" unless you want those — they bloat the archive.) Click OK.
  6. Click "Multiple formats" (still inside the My Activity row) and confirm the activity format is HTML. JSON is offered as a format choice, but for Gemini specifically the JSON output is shallower than the HTML — Gemini turns are emitted as one-line activity stubs in JSON whereas the HTML preserves the full prose. Counter-intuitive but true.
  7. Click "Next step" at the bottom of the page.
  8. Choose delivery method — "Send download link via email" is fine for one-off exports; "Add to Drive" if you want it to land in your Drive automatically. Pick a one-time export (not scheduled), file type ZIP, file size 50 GB.
  9. Click "Create export." Google Takeout queues the request. The page updates to "Export in progress."
  10. Wait 4–48 hours. Yes, really. Takeout's queue depth varies; for Gemini-only requests the typical turnaround is 4–8 hours, but enterprise Workspace accounts or accounts with years of activity can take a full day or two. Google emails when it's ready. The email comes from noreply-takeout@google.com with subject "Your Google data archive is ready."

What's actually in the archive

The ZIP unpacks to a directory tree:

Takeout/
└── My Activity/
    └── Gemini Apps/
        └── MyActivity.html

One MyActivity.html file containing every Gemini turn you've ever made. For accounts with significant history (50,000+ turns), Takeout splits this into per-month files (MyActivity-2024-12.html, etc.) — same shape, smaller per-file.

Each turn is a flat <div> with three things: the timestamp, the prompt or response prose, and a "details" link. The shape is roughly:

<div class="content-cell">
  Used Gemini Apps<br>
  <a href="...">Prompted with: "Should we adopt CockroachDB for the metrics service?"</a><br>
  Apr 28, 2026, 10:42:13 AM PDT
</div>
<div class="content-cell">
  Used Gemini Apps<br>
  Response: "CockroachDB is a strong fit for global multi-region writes..."<br>
  Apr 28, 2026, 10:42:24 AM PDT
</div>

Two things to notice. First, "Prompted with:" and "Response:" are the only role markers — there is no "sender": "user" or "role": "assistant" field, just the prefix in the prose. Second, there is no thread ID — adjacent prompt/response pairs that share a clock proximity (typically <30 seconds apart) belong to the same conversation, but you have to reconstruct that grouping yourself.

What's missing — five things you'd expect

Parsing the HTML into something usable

The minimum viable conversion is HTML → flat array of turn objects, each with a timestamp, a role guess, and the prose. The 30-line script below uses Node and cheerio for the HTML parse, then writes one JSON file in a shape close enough to ChatGPT's that the same downstream tools can consume it.

#!/usr/bin/env node
// gemini-html-to-json.js — convert Takeout MyActivity.html → conversations.json
// Usage: node gemini-html-to-json.js MyActivity.html > gemini-conversations.json
import { readFileSync } from 'node:fs';
import * as cheerio from 'cheerio';

const html = readFileSync(process.argv[2], 'utf8');
const $ = cheerio.load(html);

const turns = [];
$('.content-cell').each((_, el) => {
  const text = $(el).text().trim();
  // Only the "Used Gemini Apps" cells contain prompts/responses.
  if (!text.startsWith('Used Gemini Apps')) return;

  const promptMatch = text.match(/Prompted with:\s*"?([\s\S]+?)"?\s+([A-Z][a-z]+ \d+, \d+, \d+:\d+:\d+ [AP]M [A-Z]+)$/);
  const respMatch   = text.match(/^Used Gemini Apps\s+([\s\S]+?)\s+([A-Z][a-z]+ \d+, \d+, \d+:\d+:\d+ [AP]M [A-Z]+)$/);

  if (promptMatch) {
    turns.push({ role: 'user', text: promptMatch[1].trim(), ts: new Date(promptMatch[2]).toISOString() });
  } else if (respMatch && !text.includes('Prompted with:')) {
    turns.push({ role: 'assistant', text: respMatch[1].trim(), ts: new Date(respMatch[2]).toISOString() });
  }
});

// Reconstruct conversations: adjacent turns within 30 minutes of each other are one thread.
const THIRTY_MIN = 30 * 60 * 1000;
turns.sort((a, b) => new Date(a.ts) - new Date(b.ts));
const conversations = [];
let current = null;
for (const t of turns) {
  if (!current || new Date(t.ts) - new Date(current.last_ts) > THIRTY_MIN) {
    current = { uuid: `gemini-${t.ts}`, name: t.text.slice(0, 60), created_at: t.ts, last_ts: t.ts, chat_messages: [] };
    conversations.push(current);
  }
  current.chat_messages.push({ sender: t.role === 'user' ? 'human' : 'assistant', text: t.text });
  current.last_ts = t.ts;
}
process.stdout.write(JSON.stringify(conversations, null, 2));

Run it: node gemini-html-to-json.js MyActivity.html > gemini-conversations.json. The output shape mirrors Claude's chat_messages array intentionally — the WhyChose extractor's Claude loader can read this with no changes, which is why the script targets that shape rather than ChatGPT's mapping DAG. (ChatGPT's shape is more expressive but harder to write into; Claude's is the lowest-common-denominator we lean on for cross-platform normalization.)

The four edge cases the script handles imperfectly

Three sanity checks for the converted JSON

  1. Turn count matches. jq '[.[] | .chat_messages[]] | length' gemini-conversations.json should approximately equal the number of "Prompted with:" + "Response:" occurrences in the source HTML. A large discrepancy means the regex missed a turn shape.
  2. Conversation count is sane. If you have ~1,000 turns and the script produces 50 conversations, the average conversation length is 20 turns — reasonable for a thinking-partner workflow. If it produces 800 conversations, the threshold is too tight; if it produces 5, too loose.
  3. No empty conversations. jq '[.[] | select(.chat_messages | length == 0)] | length' gemini-conversations.json should be 0. Empty conversations indicate the regex grabbed a header cell as a turn marker.

How WhyChose fits in

The conversion gets you to a normalized JSON; the extractor takes it from there. The WhyChose open-source extractor already supports the Claude-shape chat_messages array the script above emits — drop gemini-conversations.json into the uploader (or pipe it to the CLI) and the same regex + Artifact + LLM passes that work on ChatGPT and Claude exports run on the Gemini-derived data. Decision records are emitted in the same shape regardless of source, so a multi-platform decision audit (some conversations from ChatGPT, some from Claude, some from Gemini) produces one unified log. Per-conversation metadata is thinner on the Gemini side (no project_uuid, reconstructed conversation boundaries) but the extracted decisions themselves are platform-agnostic — the trade-offs you reasoned about and the choice you locked in don't depend on which model you reasoned with.

Get early access

Related questions

Where is the Gemini export button — I can't find it in Settings?

There isn't one inside the Gemini app. Unlike ChatGPT and Claude, Gemini does not ship a Settings → Data Controls → Export flow. The only path is Google Takeout (takeout.google.com) — sign in, deselect everything, then re-select 'Gemini Apps Activity' specifically. Takeout queues the export and emails you a download link 4–48 hours later. The button you'd expect inside gemini.google.com simply does not exist as of April 2026.

Why is the export HTML files instead of JSON?

Google Takeout treats Gemini conversations the same way it treats Search history and YouTube comments — as activity records rendered as HTML for human review, not as structured data for re-import. The archive contains a single MyActivity.html file (or one per month if your activity is large) with each prompt and response wrapped in a div. There is no schema, no field reference, and no JSON sidecar. To get structured data out, you have to parse the HTML yourself.

What's missing from the export that I'd expect to be there?

Five things: Gem configurations (system instructions you wrote for custom Gems are not exported), per-conversation grouping (turns are flat-listed by timestamp with no thread ID), generated binary outputs (images, audio, video are referenced but not included), Workspace-account separation (personal Takeout returns nothing for chats under your work account; ask your Workspace admin to run a Vault export instead), and structured tool-use records (the rendered HTML summarizes tool calls in prose but doesn't expose them as discrete records).

Can I extract decisions from a Gemini export with the same workflow as ChatGPT or Claude?

Yes, but with a parsing pass first. The WhyChose extractor's loaders for ChatGPT and Claude consume JSON directly; for Gemini you run an HTML-to-JSON converter (the 30-line script on this page) that emits one record per turn with timestamp, role, and prose, then feed that into the same regex + LLM pass the JSON loaders use. The decision-extraction logic is platform-agnostic once the input is normalized.

Does Gemini for Google Workspace export the same way?

No. Gemini for Workspace runs under a separate identity governed by your Workspace admin, and personal Takeout cannot reach those chats. The supported path is Google Vault — your Workspace admin opens vault.google.com → Matters → New matter → Search → set source to "Gemini" → run a search and export. Vault output is in MBOX format wrapping the chat history, which then needs a different parser than the personal-Takeout HTML. Most Workspace admins do not realize Vault holds Gemini history; surface that to them with the Vault product documentation if needed.

Further reading