Export Your ChatGPT Conversations to Markdown & PDF
Ever had an insightful conversation with ChatGPT and wished you could effortlessly save or share it? I’ve built a simple solution to help you quickly export your entire conversation into beautiful Markdown or PDF formats. Whether it's for personal notes, blogging, presentations, or documentation—now you can export in just a few clicks!

Why Export Conversations?
- 📚 Documentation: Keep detailed AI interactions for future reference.
- ✍️ Blogging & Content Creation: Easily transform convos into publishable posts.
- 🖨 Presentations: Share ideas with polished, formatted PDF exports.
- 🗂 Archiving: Organize and store valuable insights.
📦 How to Use
Method 1: Install as Userscript (Recommended)
This is the safest and most convenient method:
- Install a userscript manager:
- Tampermonkey (Chrome, Firefox, Safari)
- Violentmonkey (Chrome, Firefox)
- Greasemonkey (Firefox)
- Click to install:
- Install Markdown Exporter
- Install PDF Exporter
- Open ChatGPT — you'll see new buttons in the sidebar:
- "Export as Markdown"
- "Export as PDF"
Method 2: Console Method
For Markdown Export:
- Open the ChatGPT conversation you wish to export.
- Right-click anywhere on the page and select ‘Inspect’ from the context menu.
- In the panel that opens, navigate to the ‘Console’ tab.
- Copy and paste the JavaScript snippet into the console input field, then press Enter.
(() => {
function formatDate(date = new Date()) {
return date.toISOString().split('T')[0];
}
function escapeMarkdown(text) {
return text
.replace(/\\/g, '\\\\')
.replace(/\*/g, '\\*')
.replace(/_/g, '\\_')
.replace(/`/g, '\\`')
.replace(/\n{3,}/g, '\n\n');
}
function processMessageContent(element) {
const clone = element.cloneNode(true);
// Replace <pre><code> blocks
clone.querySelectorAll('pre').forEach(pre => {
const code = pre.innerText.trim();
const langMatch = pre.querySelector('code')?.className?.match(/language-([a-zA-Z0-9]+)/);
const lang = langMatch ? langMatch[1] : '';
pre.replaceWith(`\n\n\`\`\`${lang}\n${code}\n\`\`\`\n`);
});
// Replace images and canvas with placeholders
clone.querySelectorAll('img, canvas').forEach(el => {
el.replaceWith('[Image or Canvas]');
});
// Convert remaining HTML to plain markdown-style text
return escapeMarkdown(clone.innerText.trim());
}
const messages = document.querySelectorAll('div[class*="group"]');
const lines = [];
const title = 'Conversation with ChatGPT';
const date = formatDate();
const url = window.location.href;
lines.push(`# ${title}\n`);
lines.push(`**Date:** ${date}`);
lines.push(`**Source:** [chat.openai.com](${url})\n`);
lines.push(`---\n`);
messages.forEach(group => {
const isUser = !!group.querySelector('img');
const sender = isUser ? 'You' : 'ChatGPT';
const block = group.querySelector('.markdown, .prose, .whitespace-pre-wrap');
if (block) {
const content = processMessageContent(block);
if (content) {
lines.push(`### **${sender}**\n`);
lines.push(content);
lines.push('\n---\n');
}
}
});
const markdown = lines.join('\n').trim();
const blob = new Blob([markdown], { type: 'text/markdown' });
const a = document.createElement('a');
a.download = `ChatGPT_Conversation_${date}.md`;
a.href = URL.createObjectURL(blob);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})();
For PDF Export:
- Open your desired ChatGPT conversation.
- Right-click anywhere on the page and select ‘Inspect’.
- Go to the ‘Console’ tab in the newly opened panel.
- Copy and paste the JavaScript snippet into the console input field, then press Enter.
(() => {
function formatDate(date = new Date()) {
return date.toISOString().split('T')[0];
}
function sanitize(text) {
return text.replace(/</g, '<').replace(/>/g, '>');
}
function extractFormattedContent() {
const messages = document.querySelectorAll('.text-base');
let html = '';
messages.forEach((msg, index) => {
const sender = index % 2 === 0 ? 'You' : 'ChatGPT';
const contentBlock = msg.querySelector('.whitespace-pre-wrap, .markdown, .prose');
if (!contentBlock) return;
const clone = contentBlock.cloneNode(true);
clone.querySelectorAll('pre').forEach(pre => {
const code = sanitize(pre.innerText.trim());
pre.replaceWith(`<pre><code>${code}</code></pre>`);
});
clone.querySelectorAll('img, canvas').forEach(el => {
el.replaceWith('[Image or Canvas]');
});
const cleanText = sanitize(clone.innerText.trim()).replace(/\n/g, '<br>');
html += `
<div class="message">
<div class="sender">${sender}</div>
<div class="content">${cleanText}</div>
</div>
`;
});
return html;
}
const date = formatDate();
const source = window.location.href;
const conversationHTML = extractFormattedContent();
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ChatGPT Conversation - ${date}</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
max-width: 800px;
margin: auto;
padding: 2rem;
background: #fff;
color: #333;
}
h1 {
text-align: center;
}
.meta {
font-size: 0.9rem;
color: #555;
margin-bottom: 2rem;
text-align: center;
}
.message {
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid #ddd;
}
.sender {
font-weight: bold;
font-size: 1.1rem;
margin-bottom: 0.5rem;
}
pre {
background: #f4f4f4;
padding: 1rem;
overflow-x: auto;
border-radius: 5px;
font-family: monospace;
font-size: 0.9rem;
}
code {
white-space: pre-wrap;
}
.content {
line-height: 1.5;
}
</style>
</head>
<body>
<h1>ChatGPT Conversation</h1>
<div class="meta">
<div><strong>Date:</strong> ${date}</div>
<div><strong>Source:</strong> <a href="${source}">${source}</a></div>
</div>
${conversationHTML}
<script>
window.onload = () => {
window.print();
};
</script>
</body>
</html>
`;
const blob = new Blob([html], { type: 'text/html' });
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
})();
Happy exporting! 🎉
It’s that easy! You now have an effortless way to archive, document, and share your valuable ChatGPT conversations.
You can explore, use, and even contribute to the original code here:
Feel free to reach out with any feedback or suggestions. Happy exporting!