Last active
July 7, 2025 10:29
-
-
Save FonzTech/ce8226dfeeac7a9ec98427d169acfabb to your computer and use it in GitHub Desktop.
Bulk Copy ChatGPT conversation. No plugins required.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copy-paste this in your browser developer console. | |
This script works on an already-opened conversation in ChatGPT. | |
Each message has a "copy" button, that copies markdown text, | |
which can be placed in MD Editor and exported to PDF. | |
To automate the task of iterating these buttons and copying | |
into a file, I created this script that can be configured and | |
edited further to suit your needs. | |
IMPORTANT: you must give clipboard permissions in your browser!! | |
IMPORTANT 2: this script works by continuously clipboard copying | |
chat contents. To do so, it's required that page "Document" is | |
focused. So, the entire script is wrapped inside a once-timer. | |
After you run the script, click the text contents in your chat | |
to give focus to the "Document" DOM element. | |
*/ | |
{ | |
// Configuration | |
// Separator between questions and answers | |
const qa_separator = '\n---\n'; // '\\newpage\n' | |
/* | |
Time increment between clipboard copy buttons, in milliseconds | |
This value is required because clipboard copy instruction is done via button click callback, | |
not the bare clipboard copy instruction. | |
This time depends on your machine and setup. If you find duplicated text after this script | |
run, you can try increasing this value. | |
*/ | |
let timeinc = 80; | |
/* | |
Initial delay time, in milliseconds. | |
Just set enough time so you can run the script in your browser console, | |
then click the page contenets to give focus to its document. | |
*/ | |
let initdelay = 2000; | |
// Script | |
let text = ""; | |
setTimeout(async () => { | |
let i = 1; | |
let user = true; | |
document.querySelectorAll('div.composer-parent button[data-testid="copy-turn-action-button"]').forEach(async (btn) => { | |
setTimeout(() => { | |
btn.click(); | |
}, i); | |
i += timeinc; | |
setTimeout(async () => { | |
const contents = await navigator.clipboard.readText(); | |
if (user) { | |
if (text.length) { | |
text += qa_separator; | |
} | |
text += "**You asked:**\n" + contents + "\n---\n\n"; | |
} else { | |
text += contents + '\n'; | |
} | |
user = !user; | |
}, i); | |
i += timeinc; | |
}); | |
i += timeinc; | |
setTimeout(() => { | |
navigator.clipboard.writeText(text); | |
console.log("Successfully copied string with length " + text.length + " in " + i + " ms!"); | |
}, i); | |
}, initdelay); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment