Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ This Firefox extension focuses exclusively on providing a lightweight yet powerf

| Feature | Description |
| -------------------------------- | ------------------------------------------------------------------------------------------ |
| **Multi-Platform Support** | Backup conversations from both Claude.ai and ChatGPT |
| **Multi-Platform Support** | Backup conversations from both Claude.ai and ChatGPT |
| **Complete Data Structure** | Preserves entire conversation history including Claude's thinking process |
| **Single Chat Backup** | Export just your current conversation with one click |
| **Bulk Backup (Claude only)** | Download all Claude conversations at once |
| **Bulk Backup** | Download all Claude or ChatGPT conversations at once |
| **Intuitive Interface** | Clean, simple UI with platform-specific styling |
| **Structured JSON Format** | Easy to process with downstream tools and analysis |
| **Privacy-Focused** | Your data stays on your device, no third-party servers |
Expand Down Expand Up @@ -94,7 +94,9 @@ The extension uses your existing authenticated sessions to access the APIs, so i

1. Navigate to [ChatGPT](https://chatgpt.com) and open a conversation
2. Click on the HumainLabs extension icon in your Firefox toolbar
3. Click on "Backup Current ChatGPT Chat" to save the current conversation
3. Choose either:
- "Backup Current ChatGPT Chat" to save only the current conversation
- "Backup All ChatGPT Conversations" to save all your conversations

For both services, you'll be prompted to choose where to save the JSON file. The file will be named with the chat title and timestamp.

Expand Down
57 changes: 57 additions & 0 deletions src/chat_export_background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,61 @@ async function exportCurrentChatGPT() {
}
}

async function exportConversationsChatGPT() {
const token = await getChatGPTAccessToken();

const conversations = [];
let offset = 0;
while (true) {
const response = await fetch(
`https://${DOMAIN_CHATGPT}/backend-api/conversations?offset=${offset}&limit=100&order=updated&is_archived=false`,
{
credentials: "include",
headers: {
"User-Agent": window.navigator.userAgent,
Accept: "*/*",
"Accept-Language": navigator.language,
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
"Alt-Used": DOMAIN_CHATGPT,
Pragma: "no-cache",
"Cache-Control": "no-cache",
},
method: "GET",
mode: "cors",
}
);
const responseJson = await response.json();
conversations.push(...responseJson.items);
if (responseJson.items.length < 100) {
break;
} else {
offset += 100;
}
}

await showNotification(
"HumainLabs ChatGPT Backup",
`Start loading ${conversations.length} conversations...`
);

const allConversationData = await Promise.all(
conversations.map(conv =>
getChatGPTConversation(conv.id)
)
);

await downloadJson(
allConversationData,
`${formatDateForFilename()}_chatgpt_all_conversations.json`
);

await showNotification(
"HumainLabs ChatGPT Backup",
`Successfully exported ${allConversationData.length} conversations!`
);
}

// Handle messages from the popup
bgBrowserAPI.runtime.onMessage.addListener((message: any, sender: MessageSender) => {
bgLogger.log("Received message:", message.action);
Expand All @@ -514,5 +569,7 @@ bgBrowserAPI.runtime.onMessage.addListener((message: any, sender: MessageSender)
exportCurrentChat();
} else if (message.action === "exportCurrentChatGPT") {
exportCurrentChatGPT();
} else if (message.action === "exportConversationsChatGPT") {
exportConversationsChatGPT();
}
});
3 changes: 3 additions & 0 deletions src/html/chat_export_popup.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ <h2>Claude & ChatGPT Backup</h2>
<li class="function-item">
<button id="exportCurrentChatGPTBtn" class="chatgpt-btn">Backup Current ChatGPT Chat</button>
</li>
<li class="function-item">
<button id="exportConversationsChatGPTBtn" class="chatgpt-btn">Backup All ChatGTP Conversations</button>
</li>
</ul>
<div class="footer">
Created by <a href="https://humainlabs.ai" target="_blank">HumainLabs.ai</a>
Expand Down
8 changes: 8 additions & 0 deletions src/ui/chat_export_popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ document.addEventListener('DOMContentLoaded', () => {
const exportConversationsBtn = document.getElementById('exportConversationsBtn');
const exportCurrentChatBtn = document.getElementById('exportCurrentChatBtn');
const exportCurrentChatGPTBtn = document.getElementById('exportCurrentChatGPTBtn');
const exportConversationsChatGPTBtn = document.getElementById('exportConversationsChatGPTBtn');

if (exportConversationsBtn) {
exportConversationsBtn.addEventListener('click', () => {
Expand All @@ -46,4 +47,11 @@ document.addEventListener('DOMContentLoaded', () => {
popupBrowserAPI.runtime.sendMessage({ action: "exportCurrentChatGPT" });
});
}

if (exportConversationsChatGPTBtn) {
exportConversationsChatGPTBtn.addEventListener('click', () => {
popupLogger.log('Clicked: Export All ChatGPT Conversations');
popupBrowserAPI.runtime.sendMessage({ action: "exportConversationsChatGPT" });
});
}
});