Skip to content

Instantly share code, notes, and snippets.

@sbolel
Last active November 4, 2025 12:10
Show Gist options
  • Select an option

  • Save sbolel/a2b2bfde16b3ab185fbc2e2049240abc to your computer and use it in GitHub Desktop.

Select an option

Save sbolel/a2b2bfde16b3ab185fbc2e2049240abc to your computer and use it in GitHub Desktop.
Instagram Comment Activity Deleter: Automate the deletion of all your Instagram comments from the 'Your Activity' section. Perfect for quick digital clean-up.
/**
* This script automates the process of deleting your own Instagram comments.
* It deletes comments in batches to avoid hitting rate limits or breaking the page.
*
* WARNING: This function directly manipulates the DOM and depends on the current HTML
* structure of Instagram's website to work. If Instagram implements changes to the
* activity page layout, structure, or functionality, this script may break or cause
* unexpected behavior. Use at your own risk and always review code before running it.
*
* How to use:
* 1. Navigate to the Instagram comments page by going to:
* https://www.instagram.com/your_activity/interactions/comments
* 2. Open the developer console in your web browser:
* - Chrome/Firefox: Press Ctrl+Shift+J (Windows/Linux) or Cmd+Option+J (Mac)
* - Safari: Enable the Develop menu in Safari's Advanced preferences, then press Cmd+Option+C
* 3. Copy and paste this entire script into the console and press Enter to run it.
*
* How to navigate to the comments page on instagram.com:
* 1. Log in to Instagram on a desktop browser.
* 2. Go to your profile by clicking on the profile icon at the bottom right.
* 3. Click on "Your Activity" in the menu.
* 4. Select "Interactions" and then "Comments".
* 5. Follow the usage steps above to run this script.
*/
;(async function () {
// Constants
/** @const {number} - The number of comments to delete in each batch. */
const DELETION_BATCH_SIZE = 3
/** @const {number} - The delay between actions in milliseconds. */
const DELAY_BETWEEN_ACTIONS_MS = 1000
/** @const {number} - The delay between clicking the checkboxes in milliseconds. */
const DELAY_BETWEEN_CHECKBOX_CLICKS_MS = 300
/** @const {number} - The maximum number of retries for waiting operations */
const MAX_RETRIES = 60
/**
* Utility function that delays execution for a given amount of time.
* @param {number} ms - The milliseconds to delay.
* @returns {Promise<void>} A promise that resolves after the specified delay.
*/
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
/**
* Utility function that waits for an element to appear in the DOM before resolving.
* @param {string} selector - The CSS selector of the element to wait for.
* @param {number} [timeout=30000] - The maximum time to wait in milliseconds.
* @returns {Promise<Element>} A promise that resolves with the found element.
* @throws {Error} If the element is not found within the timeout period.
*/
const waitForElement = async (selector, timeout = 30000) => {
const startTime = Date.now()
while (Date.now() - startTime < timeout) {
const element = document.querySelector(selector)
if (element) return element
await delay(100)
}
throw new Error(`Element with selector "${selector}" not found within ${timeout}ms`)
}
/**
* Utility function that clicks on a given element.
* @param {Element} element - The element to click.
* @throws {Error} If the element is not found.
*/
const clickElement = async (element) => {
if (!element) throw new Error('Element not found')
element.click()
}
/**
* Waits for the "Select" button to reappear after the page loads more comments
* following the deletion of a batch of comments when the "Select" button
* is hidden while a spinner indicates that more comments are loading.
* @returns {Promise<void>} A promise that resolves when the select button reappears.
* @throws {Error} If the select button is not found after maximum retries.
*/
const waitForSelectButton = async () => {
for (let i = 0; i < MAX_RETRIES; i++) {
const buttonCount = document.querySelectorAll('[role="button"]')?.length
if (buttonCount > 1) return
await delay(1000)
}
throw new Error('Select button not found after maximum retries')
}
/**
* Deletes the currently selected comments.
* @returns {Promise<void>} A promise that resolves when the comments are deleted.
*/
const deleteSelectedComments = async () => {
try {
const deleteButton = await waitForElement('[aria-label="Delete"]')
await clickElement(deleteButton)
await delay(DELAY_BETWEEN_ACTIONS_MS)
const confirmButton = await waitForElement('button[tabindex="0"]')
await clickElement(confirmButton)
} catch (error) {
console.error('Error during comment deletion:', error.message)
}
}
/**
* Deletes all user comments by selecting comments in batches.
* @returns {Promise<void>} A promise that resolves when all comments are deleted.
*/
const deleteActivity = async () => {
try {
while (true) {
const [, selectButton] = document.querySelectorAll('[role="button"]')
if (!selectButton) throw new Error('Select button not found')
await clickElement(selectButton)
await delay(DELAY_BETWEEN_ACTIONS_MS)
const checkboxes = document.querySelectorAll('[aria-label="Toggle checkbox"]')
if (checkboxes.length === 0) {
console.log('No more comments to delete')
break
}
for (let i = 0; i < Math.min(DELETION_BATCH_SIZE, checkboxes.length); i++) {
await clickElement(checkboxes[i])
await delay(DELAY_BETWEEN_CHECKBOX_CLICKS_MS)
}
await delay(DELAY_BETWEEN_ACTIONS_MS)
await deleteSelectedComments()
await delay(DELAY_BETWEEN_ACTIONS_MS)
await waitForSelectButton()
await delay(DELAY_BETWEEN_ACTIONS_MS)
}
} catch (error) {
console.error('Error in deleteActivity:', error.message)
}
}
// Start the deletion process
try {
await deleteActivity()
console.log('Activity deletion completed')
} catch (error) {
console.error('Fatal error:', error.message)
}
})()
@theshubzworld
Copy link

theshubzworld commented Nov 4, 2025

📌 Instagram Comment Bulk Deletion Script (Python + Selenium)

Description:

Automates the deletion of your Instagram comments (or likes) in batches.

Features interactive prompts for:

- How many selections per batch

- Delay between each selection (sec)

- Delay after each batch deletion (sec)

- Customizable rate-limit retry timer

Progress and batch info shown in the terminal.

import logging
import pathlib
import platform
import random
import sys
import time

from selenium import webdriver
from selenium.common.exceptions import (
NoSuchWindowException,
TimeoutException,
StaleElementReferenceException,
)
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait

logging.basicConfig(format="[%(levelname)s] Instagram Cleaner: %(message)s", level=logging.INFO)

def get_int_input(prompt, default):
while True:
try:
inp = input(f"{prompt} (default: {default}) [x]: ")
if not inp or inp.lower() == "x":
return default
value = int(inp)
if value <= 0:
print("Please enter a positive integer.")
continue
return value
except ValueError:
print("Invalid input. Please enter a number.")

def get_float_input(prompt, default):
while True:
try:
inp = input(f"{prompt} (default: {default}) [x]: ")
if not inp or inp.lower() == "x":
return default
value = float(inp)
if value <= 0:
print("Please enter a positive number.")
continue
return value
except ValueError:
print("Invalid input. Please enter a number.")

print("---- Instagram Bulk Comment Cleaner ----")
SELECTIONS_AT_ONCE = get_int_input("How many comments to select (per batch)?", 5)
DELAY_BETWEEN_SELECTS = get_float_input("Delay (seconds) between each selection?", 2.0)
DELAY_AFTER_BATCH_DELETE = get_float_input("Delay (seconds) after each batch deletion?", 10.0)
CHECK_EVERY = get_float_input("If rate limit hit, wait how many hours before retry? ", 1.0) * 3600
MODE = 1 # 1 = comments, 2 = likes
print("----------------------------------------")

LIKES_URL = "https://www.instagram.com/your_activity/interactions/likes"
COMMENTS_URL = "https://www.instagram.com/your_activity/interactions/comments"

logging.info("Starting script...")

try:
options = Options()
wd = pathlib.Path().absolute()

if platform.system() == "Windows":
    options.add_argument(f"user-data-dir={wd}\\chrome-profile")
else:
    options.add_argument("user-data-dir=chrome-profile")

driver = webdriver.Chrome(options=options)
logging.info("Chrome browser launched")

URL = COMMENTS_URL if MODE == 1 else LIKES_URL
driver.get(URL)
logging.info(f"Opening page: {URL}")

# Wait for user to log in manually
while True:
    if driver.current_url.startswith(URL):
        logging.info("Login detected")
        break
    try:
        logging.info("Waiting for login (log in from the browser and don't click anything else)...")
        wait = WebDriverWait(driver, 60)

        def is_not_now_button_present(driver):
            try:
                div = driver.find_element(By.CSS_SELECTOR, "div[role='button']")
                return div.text in ["Not now", "Plus tard"]
            except:
                return False

        wait.until(is_not_now_button_present)
        driver.find_element(By.CSS_SELECTOR, "div[role='button']").send_keys(Keys.ENTER)
        logging.info("Clicked 'Not now'")
        break
    except TimeoutException:
        pass

# Main loop
total_deleted = 0
batch_number = 1
while True:
    is_clicked_select = False
    while not is_clicked_select:
        logging.info("Waiting for elements to load...")
        time.sleep(2)
        elements = driver.find_elements(By.CSS_SELECTOR, 'span[data-bloks-name="bk.components.Text"]')
        for el in elements:
            if el.text in ["Select", "Sélectionner"]:
                if any(txt.text in ["No results", "Aucun résultat"] for txt in elements):
                    logging.info("No items found. Finished.")
                    driver.quit()
                    sys.exit(0)
                driver.execute_script("arguments[0].click();", el)
                logging.info("Clicked 'Select'")
                is_clicked_select = True
                break

    selected_count = 0
    attempts = 0
    refreshed = False

    while selected_count < SELECTIONS_AT_ONCE:
        if refreshed:
            break
        time.sleep(DELAY_BETWEEN_SELECTS)
        for checkbox in driver.find_elements(By.CSS_SELECTOR, '[aria-label="Toggle checkbox"]'):
            try:
                if not checkbox.is_selected():
                    driver.execute_script("arguments[0].click();", checkbox)
                    selected_count += 1
                    logging.info(f"Selected item (Total: {selected_count})")
                    if selected_count >= SELECTIONS_AT_ONCE:
                        break
            except StaleElementReferenceException:
                continue

        attempts += 1
        if attempts > 10:
            logging.warning("Possible UI issue or limit. Retrying...")
            time.sleep(2)
            attempts = 0

    # Click Delete/Unlike
    deleted_this_batch = False
    for span in driver.find_elements(By.CSS_SELECTOR, 'span[data-bloks-name="bk.components.TextSpan"]'):
        if span.text in (["Delete", "Supprimer"] if MODE == 1 else ["Unlike", "Je n’aime plus"]):
            time.sleep(1)
            driver.execute_script("arguments[0].click();", span)
            logging.info(f"Clicked '{span.text}' to confirm deletion (Batch #{batch_number})")
            deleted_this_batch = True
            break

    # Confirm the deletion
    confirmed = False
    while not confirmed and deleted_this_batch:
        time.sleep(1)
        for btn in driver.find_elements(By.CSS_SELECTOR, 'div[role="dialog"] button'):
            try:
                confirmation_text = btn.find_element(By.CSS_SELECTOR, "div").text
                if confirmation_text in ["Delete", "Unlike", "Supprimer", "Je n’aime plus"]:
                    driver.execute_script("arguments[0].click();", btn)
                    logging.info(f"Confirmed '{confirmation_text}'")
                    total_deleted += selected_count
                    logging.info(f"Deleted {selected_count} comments in batch #{batch_number}. Total deleted: {total_deleted}")
                    batch_number += 1
                    confirmed = True
                    break
            except StaleElementReferenceException:
                continue
        if not confirmed:
            time.sleep(1)

    logging.info(f"Waiting {DELAY_AFTER_BATCH_DELETE} seconds before next batch...")
    time.sleep(DELAY_AFTER_BATCH_DELETE)  # Extra delay for safety

except KeyboardInterrupt:
logging.info("Script manually interrupted.")
driver.quit()
sys.exit(0)
except NoSuchWindowException:
logging.exception("Browser window was closed.")
sys.exit(1)
except Exception as e:
logging.exception("Unexpected error:")
try:
driver.quit()
except:
pass
sys.exit(1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment