Created
November 25, 2025 16:20
-
-
Save syauqi/537940876cd50b96fc9342bd5cc9d708 to your computer and use it in GitHub Desktop.
Auto delete comments you've made in Instagram
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
| /** | |
| * Instagram Comment Auto-Deletion Script (Enhanced Version) | |
| * | |
| * ⚠️ IMPORTANT WARNINGS: | |
| * - This script likely violates Instagram's Terms of Service | |
| * - Your account could be temporarily or permanently banned for using automation | |
| * - Instagram may update their UI at any time, breaking this script | |
| * - Use at your own risk - test with small batches first | |
| * | |
| * REQUIREMENTS: | |
| * - Instagram UI language must be set to English | |
| * - Must be on: https://www.instagram.com/your_activity/interactions/comments | |
| * | |
| * HOW TO USE: | |
| * 1. Navigate to: https://www.instagram.com/your_activity/interactions/comments | |
| * 2. Open Developer Console (F12 or Ctrl+Shift+J / Cmd+Option+J) | |
| * 3. Paste this entire script and press Enter | |
| * 4. The script will start automatically | |
| * 5. To stop: Close the tab or refresh the page | |
| * | |
| * FEATURES: | |
| * - Automatic error recovery | |
| * - Progress tracking with statistics | |
| * - Configurable batch sizes and delays | |
| * - Better performance than original | |
| * - Clearer logging and status updates | |
| */ | |
| ;(async function() { | |
| 'use strict'; | |
| // ==================== CONFIGURATION ==================== | |
| const CONFIG = { | |
| BATCH_SIZE: 15, // Comments to delete per batch | |
| DELAY_BETWEEN_BATCHES: 2000, // Wait between batches (ms) | |
| DELAY_BETWEEN_CHECKBOXES: 250, // Wait between checkbox clicks (ms) | |
| DELAY_AFTER_DELETE: 2000, // Wait after clicking delete (ms) | |
| DELAY_AFTER_SELECT: 3000, // Wait after clicking "Select" button (ms) | |
| SCROLL_DELAY: 1500, // Wait for content to load after scroll (ms) | |
| MAX_SCROLL_ATTEMPTS: 5, // Max attempts to load more comments | |
| ELEMENT_WAIT_TIMEOUT: 10000, // Max wait for elements (ms) | |
| ERROR_RETRY_DELAY: 5000, // Wait before retrying after error (ms) | |
| }; | |
| // ==================== UTILITY FUNCTIONS ==================== | |
| const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); | |
| const log = { | |
| info: (msg) => console.log(`ℹ️ ${msg}`), | |
| success: (msg) => console.log(`✅ ${msg}`), | |
| warning: (msg) => console.warn(`⚠️ ${msg}`), | |
| error: (msg) => console.error(`❌ ${msg}`), | |
| progress: (msg) => console.log(`⏳ ${msg}`), | |
| }; | |
| // Statistics tracker | |
| const stats = { | |
| deleted: 0, | |
| errors: 0, | |
| batches: 0, | |
| startTime: Date.now(), | |
| report() { | |
| const elapsed = Math.floor((Date.now() - this.startTime) / 1000); | |
| const minutes = Math.floor(elapsed / 60); | |
| const seconds = elapsed % 60; | |
| log.info(`📊 Stats: ${this.deleted} deleted | ${this.batches} batches | ${this.errors} errors | Time: ${minutes}m ${seconds}s`); | |
| } | |
| }; | |
| /** | |
| * Wait for an element to appear in the DOM | |
| */ | |
| const waitForElement = async (selector, timeout = CONFIG.ELEMENT_WAIT_TIMEOUT) => { | |
| const startTime = Date.now(); | |
| while (Date.now() - startTime < timeout) { | |
| const element = document.querySelector(selector); | |
| if (element && element.offsetParent !== null) return element; | |
| await delay(100); | |
| } | |
| return null; | |
| }; | |
| /** | |
| * Find element by text content (supports multiple languages) | |
| */ | |
| const findByText = (text, tag = '*') => { | |
| const texts = Array.isArray(text) ? text : [text]; | |
| return Array.from(document.querySelectorAll(tag)).find(el => | |
| texts.some(t => el.textContent.trim() === t) | |
| ); | |
| }; | |
| /** | |
| * Safely click an element with scroll into view | |
| */ | |
| const safeClick = async (element, description = 'element') => { | |
| if (!element) { | |
| throw new Error(`Cannot click ${description}: element not found`); | |
| } | |
| try { | |
| element.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
| await delay(300); | |
| element.click(); | |
| return true; | |
| } catch (error) { | |
| throw new Error(`Failed to click ${description}: ${error.message}`); | |
| } | |
| }; | |
| /** | |
| * Check if we're on the correct page | |
| */ | |
| const verifyPage = () => { | |
| const url = window.location.href; | |
| if (!url.includes('instagram.com/your_activity/interactions/comments')) { | |
| log.error('Wrong page! Please navigate to: https://www.instagram.com/your_activity/interactions/comments'); | |
| return false; | |
| } | |
| return true; | |
| }; | |
| /** | |
| * Dismiss any error dialogs that might appear | |
| */ | |
| const dismissErrors = async () => { | |
| const errorButtons = [ | |
| findByText(['OK', 'Okay', 'Close', 'Dismiss'], 'button'), | |
| findByText(['OK', 'Okay', 'Close', 'Dismiss'], 'div') | |
| ].filter(Boolean); | |
| for (const button of errorButtons) { | |
| try { | |
| await safeClick(button, 'error dialog'); | |
| await delay(500); | |
| log.warning('Dismissed error dialog'); | |
| } catch (e) { | |
| // Ignore if can't dismiss | |
| } | |
| } | |
| }; | |
| /** | |
| * Scroll to load more comments | |
| */ | |
| const scrollForMore = async () => { | |
| const beforeScroll = document.querySelectorAll('[aria-label="Toggle checkbox"]').length; | |
| window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); | |
| await delay(CONFIG.SCROLL_DELAY); | |
| const afterScroll = document.querySelectorAll('[aria-label="Toggle checkbox"]').length; | |
| return afterScroll > beforeScroll; | |
| }; | |
| /** | |
| * Get all available checkboxes | |
| */ | |
| const getCheckboxes = () => { | |
| return Array.from(document.querySelectorAll('[aria-label="Toggle checkbox"]')) | |
| .filter(cb => cb.offsetParent !== null); // Only visible checkboxes | |
| }; | |
| /** | |
| * Click the "Select" button to enter selection mode | |
| */ | |
| const enterSelectionMode = async () => { | |
| log.progress('Looking for Select button...'); | |
| const selectButton = findByText(['Select', 'Wählen'], 'span'); | |
| if (!selectButton) { | |
| throw new Error('Select button not found'); | |
| } | |
| await safeClick(selectButton, 'Select button'); | |
| await delay(CONFIG.DELAY_AFTER_SELECT); | |
| log.success('Entered selection mode'); | |
| }; | |
| /** | |
| * Select a batch of comments | |
| */ | |
| const selectComments = async (count) => { | |
| const checkboxes = getCheckboxes(); | |
| const toSelect = Math.min(count, checkboxes.length); | |
| if (toSelect === 0) { | |
| return 0; | |
| } | |
| log.progress(`Selecting ${toSelect} comments...`); | |
| for (let i = 0; i < toSelect; i++) { | |
| try { | |
| await safeClick(checkboxes[i], `checkbox ${i + 1}`); | |
| await delay(CONFIG.DELAY_BETWEEN_CHECKBOXES); | |
| } catch (error) { | |
| log.warning(`Failed to click checkbox ${i + 1}: ${error.message}`); | |
| } | |
| } | |
| return toSelect; | |
| }; | |
| /** | |
| * Delete selected comments | |
| */ | |
| const deleteSelected = async () => { | |
| log.progress('Looking for Delete button...'); | |
| const deleteButton = findByText(['Delete', 'Löschen'], 'span'); | |
| if (!deleteButton) { | |
| throw new Error('Delete button not found'); | |
| } | |
| await safeClick(deleteButton, 'Delete button'); | |
| await delay(CONFIG.DELAY_AFTER_DELETE); | |
| // Confirm deletion | |
| log.progress('Confirming deletion...'); | |
| const confirmButton = await waitForElement('button[tabindex="0"]'); | |
| if (!confirmButton) { | |
| throw new Error('Confirm button not found'); | |
| } | |
| await safeClick(confirmButton, 'Confirm button'); | |
| await delay(CONFIG.DELAY_AFTER_DELETE); | |
| log.success('Comments deleted'); | |
| }; | |
| /** | |
| * Wait for selection mode to exit (back to normal view) | |
| */ | |
| const waitForNormalMode = async () => { | |
| log.progress('Waiting for UI to reset...'); | |
| let attempts = 0; | |
| while (attempts < 30) { | |
| const selectButton = findByText(['Select', 'Wählen'], 'span'); | |
| if (selectButton) { | |
| await delay(500); | |
| return true; | |
| } | |
| await delay(500); | |
| attempts++; | |
| } | |
| log.warning('UI did not reset as expected, continuing anyway...'); | |
| return false; | |
| }; | |
| /** | |
| * Main deletion loop for a single batch | |
| */ | |
| const deleteBatch = async () => { | |
| try { | |
| // Dismiss any error dialogs first | |
| await dismissErrors(); | |
| // Enter selection mode | |
| await enterSelectionMode(); | |
| // Check if there are comments to delete | |
| let checkboxes = getCheckboxes(); | |
| if (checkboxes.length === 0) { | |
| log.info('No checkboxes found, attempting to scroll for more...'); | |
| const loadedMore = await scrollForMore(); | |
| if (!loadedMore) { | |
| log.info('No more comments to load'); | |
| return false; | |
| } | |
| checkboxes = getCheckboxes(); | |
| } | |
| if (checkboxes.length === 0) { | |
| log.warning('Still no comments found after scrolling'); | |
| return false; | |
| } | |
| // Select comments | |
| const selected = await selectComments(CONFIG.BATCH_SIZE); | |
| if (selected === 0) { | |
| log.warning('No comments could be selected'); | |
| return false; | |
| } | |
| // Delete selected comments | |
| await deleteSelected(); | |
| // Update stats | |
| stats.deleted += selected; | |
| stats.batches++; | |
| // Wait for UI to return to normal | |
| await waitForNormalMode(); | |
| // Delay between batches | |
| await delay(CONFIG.DELAY_BETWEEN_BATCHES); | |
| return true; | |
| } catch (error) { | |
| stats.errors++; | |
| log.error(`Batch deletion failed: ${error.message}`); | |
| // Try to recover | |
| await delay(CONFIG.ERROR_RETRY_DELAY); | |
| return true; // Continue anyway | |
| } | |
| }; | |
| /** | |
| * Main execution function | |
| */ | |
| const run = async () => { | |
| log.info('================================================='); | |
| log.info('Instagram Comment Auto-Deletion Script Starting'); | |
| log.info('================================================='); | |
| // Verify we're on the correct page | |
| if (!verifyPage()) { | |
| return; | |
| } | |
| log.info('Waiting for page to fully load...'); | |
| await delay(3000); | |
| log.success('Starting deletion process...'); | |
| log.warning('To stop: Close this tab or refresh the page'); | |
| let consecutiveFailures = 0; | |
| const maxConsecutiveFailures = 3; | |
| while (true) { | |
| const success = await deleteBatch(); | |
| if (success) { | |
| consecutiveFailures = 0; | |
| stats.report(); | |
| } else { | |
| consecutiveFailures++; | |
| log.warning(`No comments deleted (attempt ${consecutiveFailures}/${maxConsecutiveFailures})`); | |
| if (consecutiveFailures >= maxConsecutiveFailures) { | |
| log.success('No more comments found after multiple attempts'); | |
| break; | |
| } | |
| await delay(CONFIG.ERROR_RETRY_DELAY); | |
| } | |
| } | |
| log.info('================================================='); | |
| log.success('Deletion process completed!'); | |
| stats.report(); | |
| log.info('================================================='); | |
| }; | |
| // ==================== START SCRIPT ==================== | |
| try { | |
| await run(); | |
| } catch (error) { | |
| log.error(`Fatal error: ${error.message}`); | |
| log.error(error.stack); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment