ChatGPT Bulk Delete Script

A lightweight browser script by GamerDesigns that lets you select and delete multiple chats at once.

Install Guide

How to install this script

Follow these steps in order. This was written to be as easy as possible, even if you have never used a browser script before.

Before you start

You need Google Chrome, the Tampermonkey extension, and a normal ChatGPT account logged in through the website.

1

Use Google Chrome

This script works best in Google Chrome. If you do not already have Chrome installed, download it first.

Download Google Chrome
2

Install Tampermonkey

Open the Chrome Web Store page below, then click Add to Chrome.

Install Tampermonkey
3

Create a new script

  • Click the Tampermonkey icon in the top right of Chrome
  • Click Create a new script
4

Paste the script

  • Delete everything in the editor
  • Click Copy Script on this page
  • Paste it into Tampermonkey
5

Save the script

Press CTRL + S on your keyboard, or click File → Save.

6

Open ChatGPT

Once the script is saved, open ChatGPT in your browser.

Open ChatGPT
7

Use the tool

Click Scan Chats Click Select Mode Pick the chats you want Click Delete Selected
Important: Test the script on 1 or 2 chats first before trying to delete a bigger batch.
ChatGPT Bulk Delete Script Author: GamerDesigns
// ==UserScript==
// @name         ChatGPT Bulk Delete UI Click
// @namespace    gamerdesigns.chatgpt.bulkdelete.uiclick
// @version      1.0.1
// @description  Bulk delete selected ChatGPT chats by using the normal UI menu
// @author       GamerDesigns
// @match        https://chatgpt.com/*
// @match        https://chat.openai.com/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function () {
  'use strict';

  const PANEL_ID = 'gd-bulk-ui-panel';
  const STYLE_ID = 'gd-bulk-ui-style';
  const CHECKBOX_CLASS = 'gd-bulk-ui-checkbox';
  const ROW_ATTR = 'data-gd-bulk-row';

  let selectMode = false;
  let busy = false;

  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  function injectStyles() {
    if (document.getElementById(STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = STYLE_ID;
    style.textContent = `
      #${PANEL_ID}{position:fixed;right:16px;bottom:16px;z-index:999999;background:#0f172a;color:#fff;border:1px solid rgba(255,255,255,.12);border-radius:16px;padding:14px;box-shadow:0 10px 30px rgba(0,0,0,.35);width:290px;font-family:Arial,sans-serif}
      #${PANEL_ID} .title{font-size:18px;font-weight:700;margin:0 0 12px}
      #${PANEL_ID} .row{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px}
      #${PANEL_ID} button{background:#334155;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:12px;padding:10px 14px;font-size:14px;cursor:pointer}
      #${PANEL_ID} button:hover{background:#475569}
      #${PANEL_ID} .danger{background:#991b1b}
      #${PANEL_ID} .danger:hover{background:#b91c1c}
      #${PANEL_ID} .count{font-size:14px;font-weight:700;color:#93c5fd}
      #${PANEL_ID} .status{font-size:14px;opacity:.9;line-height:1.35}
      .${CHECKBOX_CLASS}{width:16px;height:16px;min-width:16px;accent-color:#3b82f6;cursor:pointer}
      .gd-bulk-ui-wrap{display:none;align-items:center;justify-content:center;margin-right:8px}
      body.gd-bulk-ui-select .gd-bulk-ui-wrap{display:flex}
      body.gd-bulk-ui-select [${ROW_ATTR}="1"]{outline:1px solid rgba(59,130,246,.22);outline-offset:2px;border-radius:10px}
    `;
    document.head.appendChild(style);
  }

  function createPanel() {
    if (document.getElementById(PANEL_ID)) return;

    const panel = document.createElement('div');
    panel.id = PANEL_ID;
    panel.innerHTML = `
      
Bulk Delete UI
0 selected
Ready.
`; document.body.appendChild(panel); panel.querySelector('#gd-scan').addEventListener('click', scanChats); panel.querySelector('#gd-toggle').addEventListener('click', () => { selectMode = !selectMode; document.body.classList.toggle('gd-bulk-ui-select', selectMode); panel.querySelector('#gd-toggle').textContent = selectMode ? 'Exit Select' : 'Select Mode'; }); panel.querySelector('#gd-all').addEventListener('click', selectAllVisible); panel.querySelector('#gd-clear').addEventListener('click', clearSelection); panel.querySelector('#gd-delete').addEventListener('click', deleteSelected); document.addEventListener('change', (e) => { if (e.target && e.target.classList.contains(CHECKBOX_CLASS)) updateCount(); }); } function setStatus(text) { const el = document.getElementById('gd-status'); if (el) el.textContent = text; } function updateCount() { const count = document.querySelectorAll(`.${CHECKBOX_CLASS}:checked`).length; const el = document.getElementById('gd-count'); if (el) el.textContent = `${count} selected`; } function getConversationId(href) { const m = href && href.match(/\/c\/([a-zA-Z0-9-]+)/); return m ? m[1] : null; } function getCandidateLinks() { return Array.from(document.querySelectorAll('a[href*="/c/"]')); } function getRow(anchor) { let node = anchor; for (let i = 0; i < 8 && node; i++) { if (node.parentElement && node.parentElement.querySelector('a[href*="/c/"]')) return node.parentElement; node = node.parentElement; } return anchor.parentElement; } function scanChats() { const links = getCandidateLinks(); let added = 0; for (const link of links) { const href = link.getAttribute('href') || ''; const id = getConversationId(href); if (!id) continue; const row = getRow(link); if (!row) continue; row.setAttribute(ROW_ATTR, '1'); row.dataset.gdConversationId = id; if (row.querySelector(`.${CHECKBOX_CLASS}`)) continue; const wrap = document.createElement('div'); wrap.className = 'gd-bulk-ui-wrap'; const cb = document.createElement('input'); cb.type = 'checkbox'; cb.className = CHECKBOX_CLASS; cb.dataset.conversationId = id; wrap.appendChild(cb); row.insertBefore(wrap, row.firstChild); added++; } setStatus(`Scan complete. Added ${added} checkbox(es).`); updateCount(); } function selectAllVisible() { document.querySelectorAll(`.${CHECKBOX_CLASS}`).forEach(cb => cb.checked = true); updateCount(); } function clearSelection() { document.querySelectorAll(`.${CHECKBOX_CLASS}`).forEach(cb => cb.checked = false); updateCount(); } function getSelectedIds() { return Array.from(document.querySelectorAll(`.${CHECKBOX_CLASS}:checked`)) .map(cb => cb.dataset.conversationId) .filter(Boolean); } function getSelectedRows() { const ids = getSelectedIds(); return ids.map(id => document.querySelector(`[data-gd-conversation-id="${CSS.escape(id)}"]`)).filter(Boolean); } function isVisible(el) { if (!el) return false; const rect = el.getBoundingClientRect(); const style = window.getComputedStyle(el); return style.display !== 'none' && style.visibility !== 'hidden' && rect.width > 0 && rect.height > 0; } function findMenuButton(row) { if (!row) return null; const buttons = Array.from(row.querySelectorAll('button')); for (const btn of buttons) { const label = `${btn.getAttribute('aria-label') || ''} ${btn.getAttribute('title') || ''} ${btn.textContent || ''}`.toLowerCase(); if (label.includes('more') || label.includes('menu') || label.includes('options')) return btn; } const svgButtons = buttons.filter(isVisible); if (svgButtons.length) return svgButtons[svgButtons.length - 1]; return null; } function findDeleteMenuItem() { const candidates = Array.from(document.querySelectorAll('button, div[role="menuitem"], [role="menuitem"]')); for (const el of candidates) { const text = (el.textContent || '').trim().toLowerCase(); if (text === 'delete' || text.includes('delete chat') || text.includes('delete')) { if (isVisible(el)) return el; } } return null; } function findConfirmDeleteButton() { const candidates = Array.from(document.querySelectorAll('button')); for (const btn of candidates) { const text = (btn.textContent || '').trim().toLowerCase(); if ((text === 'delete' || text === 'delete chat' || text.includes('delete')) && isVisible(btn)) { return btn; } } return null; } async function openRowMenu(row) { row.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true })); await sleep(250); let btn = findMenuButton(row); if (!btn) { row.click(); await sleep(250); btn = findMenuButton(row); } if (!btn) throw new Error('Menu button not found'); btn.click(); await sleep(350); } async function clickDeleteInMenu() { const item = findDeleteMenuItem(); if (!item) throw new Error('Delete menu item not found'); item.click(); await sleep(400); } async function confirmDelete() { const btn = findConfirmDeleteButton(); if (!btn) throw new Error('Confirm delete button not found'); btn.click(); await sleep(900); } async function deleteRowViaUI(row) { await openRowMenu(row); await clickDeleteInMenu(); await confirmDelete(); } async function deleteSelected() { if (busy) return; const rows = getSelectedRows(); if (!rows.length) { alert('No chats selected.'); return; } if (!confirm(`Delete ${rows.length} selected chat(s)? This cannot be undone.`)) return; busy = true; let ok = 0; let fail = 0; setStatus(`Deleting ${rows.length} chat(s)...`); for (const row of rows) { try { row.scrollIntoView({ behavior: 'auto', block: 'center' }); await sleep(350); await deleteRowViaUI(row); row.remove(); ok++; setStatus(`Deleted ${ok}/${rows.length}`); } catch (err) { console.error('Delete failed:', err); fail++; setStatus(`Deleted ${ok}/${rows.length}, failed ${fail}`); } await sleep(500); } busy = false; updateCount(); setStatus(`Done. Deleted ${ok}, failed ${fail}.`); } function init() { injectStyles(); createPanel(); setStatus('Ready. Open chat history, click Scan Chats, then Select Mode.'); } init(); })();