Skip to content

Instantly share code, notes, and snippets.

@sbolel
Last active August 7, 2025 20:20
Show Gist options
  • Save sbolel/a2b2bfde16b3ab185fbc2e2049240abc to your computer and use it in GitHub Desktop.
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)
}
})()
@ArtOfficialIntelligence

It breaks for me after selecting 100 items, so I modified to stop at 100

!async function(){let e=e=>new Promise(t=>setTimeout(t,e)),t=async(t,a=3e4)=>{let r=Date.now();for(;Date.now()-r<a;){let o=document.querySelector(t);if(o)return o;await e(100)}throw Error(Element with selector "${t}" not found within ${a}ms)},a=async e=>{if(!e)throw Error("Element not found");e.click()},r=async()=>{for(let t=0;t<60;t++){if(document.querySelectorAll('[role="button"]').length>1)return;await e(1e3)}throw Error("Select button not found after maximum retries")},o=async()=>{try{await a(await t('[aria-label="Delete"]')),await e(1e3);await a(await t('button[tabindex="0"]'))}catch(r){console.error("Error during comment deletion:",r.message)}},l=async()=>{try{for(;;){let[,t]=document.querySelectorAll('[role="button"]');if(!t)throw Error("Select button not found");await a(t),await e(1e3);let l=document.querySelectorAll('[aria-label="Toggle checkbox"]');if(0===l.length){console.log("No more comments to delete");break}let i=0;for(let n of l){if(i>=100)break;await a(n),i++,await e(300)}await e(1e3),await o(),await e(1e3),await r(),await e(1e3)}}catch(c){console.error("Error in deleteActivity:",c.message)}};(async()=>{try{await l(),console.log("Activity deletion completed")}catch(e){console.error("Fatal error:",e.message)}})()}();

@jobbiecivanne
Copy link

Commenting in 2025! I am no coder but was wondering if you could offer some assistance in creating an adjustment to where it doesn't delete comments on posts from people that I follow or my posts? Is that something doable? Thanks!

@gabriellobato1987
Copy link

gabriellobato1987 commented Feb 14, 2025

This helped me SO MUCH, that i decided to create this account and share an IMPROVEMENT.

This script is based on the original in the post, BUT, there's some features.

1 - It forces the height of the DIV that contains the comments, DIV-> (_ab81) to be 10000px, that way it gets more comments at once, since the size matters to list the coments that will be deleted, in the original version you could get 3... maybe 20 if you edited it, because of the height of the DIV containing the comments.

Now it gets a lot of comments, and it deletes 99 comments at once (the limit is 100 on instagram if you are doing it manually).
You can set it to 99, but i strongly recommend to keep 40 (i did some tests and it works better with 40 or 50 comments deleted at once, because more comments equals to more time to reload the page and bring new comments, and also too many being deleted at once increases the risk of INSTAGRAM ERROR MESSAGE.

2 - If something goes WRONG (which happened a lot for me, an error message from instagram), the original script would end and thats it, you had to refresh the page to get new comments and run the script again.

3 - Sometimes the original script thinks its done, and breaks/end. It happens because no new comments are loaded in the page due to a delay from instagram, so now it waits longer, ignores the instagram 'wrong messages' and restart again from ZERO.

Now, it detects the WRONG message, and clicks "OK", to reload coments without refreshing the page, and ALSO restarts the script from ZERO, so you don't have to run it again mannually.

So basically, it makes the window bigger, to get more comments at once, the delay between actions is bigger to give enought time to load more content to delete, and then selects it, deletes it, like it did before, but if there's an error message, he says its ok, reload the page, the new comments, scroll down simulating ah human behavior to get more comments, delete, and repeat it all again.

Because the loop is almost infinite, you have to check on it sometimes to see if it's running without messages, because it may delete everything and keeps running forever, so you have to turn it off my closing the window, and them check if it is ok.

IT SAVES TIME, THANKS AGAIN FOR THE ORIGINAL ONE, I MADE THIS ONE WITH CHATGPT (since i'm not a developer, just know the basics about php/css/html).

ENJOY!

;(async function () {
// Constants
/** @const {number} - The number of comments to delete in each batch. */
const DELETION_BATCH_SIZE = 40

/** @const {number} - The delay between major actions in milliseconds. */
const DELAY_BETWEEN_ACTIONS_MS = 3000

/**

  • Now, the delay between each checkbox click is 100ms.
    */
    const DELAY_BETWEEN_CHECKBOX_CLICKS_MS = 100

/** @const {number} - The maximum number of retries for waiting operations. */
const MAX_RETRIES = 100

/**

  • Simple delay function.
  • @param {number} ms
  • @returns {Promise}
    */
    function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms))
    }

/**

  • Slowly scrolls the page in 'steps' increments over a total duration of 'totalDurationMs'.
  • Example: slowScrollDown(10000, 10) → scrolls in 200 steps over 60s.
  • @param {number} [totalDurationMs=60000] Total time in ms (default = 60s)
  • @param {number} [steps=50] Number of increments
    */
    async function slowScrollDown(totalDurationMs = 10000, steps = 10) {
    const totalHeight = document.body.scrollHeight
    const stepHeight = totalHeight / steps
    const stepDelay = totalDurationMs / steps
// Start at the top
window.scrollTo(0, 0)

for (let i = 0; i < steps; i++) {
  // Scroll down another "stepHeight"
  window.scrollBy(0, stepHeight)
  // Wait for the duration of each step
  await delay(stepDelay)
}
// At the end, ensure it is at the bottom
window.scrollTo(0, document.body.scrollHeight)

}

/**

  • Waits until an element matching the selector is found, or fails after 'timeout' ms.
  • @param {string} selector
  • @param {number} [timeout=30000]
  • @returns {Promise}
    */
    async function waitForElement(selector, timeout) {
    if (timeout === undefined) {
    timeout = 30000
    }
    const startTime = Date.now()
    while (Date.now() - startTime < timeout) {
    const el = document.querySelector(selector)
    if (el) return el
    await delay(100)
    }
    throw new Error(
    'Element with selector "' + selector + '" not found within ' + timeout + 'ms'
    )
    }

/**

  • Clicks on an element.
  • @param {Element} element
    */
    async function clickElement(element) {
    if (!element) throw new Error('Element not found')
    element.click()
    }

/**

  • Checks if there is a "wrong" message on the screen; if so, clicks "OK" and scrolls to the top.
    */
    async function handleWrongMessage() {
    const possibleMessages = document.querySelectorAll('div, span, p')
    for (const msg of possibleMessages) {
    if (msg.textContent.toLowerCase().includes('wrong')) {
    const allButtons = document.querySelectorAll('button')
    for (const btn of allButtons) {
    if (/^(ok)$/i.test(btn.textContent.trim())) {
    await clickElement(btn)
    await delay(500)
    // Scroll to the top after clicking "OK"
    window.scrollTo(0, 0)
    break
    }
    }
    break
    }
    }
    }

/**

  • Waits until the "Select" button reappears after a deletion batch.
    */
    async function waitForSelectButton() {
    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 selected comments. After "Delete" and "Confirm", scrolls to the top.
    */
    async function deleteSelectedComments() {
    try {
    const deleteButton = await waitForElement('[aria-label="Delete"]')
    await clickElement(deleteButton)
    // Wait a bit before clicking "Confirm"
    await delay(DELAY_BETWEEN_ACTIONS_MS)

    const confirmButton = await waitForElement('button[tabindex="0"]')
    await clickElement(confirmButton)
    // Scroll to the top after clicking "Delete" and "Confirm"
    window.scrollTo(0, 0)

    // Check for "wrong"
    await handleWrongMessage()
    } catch (error) {
    console.error('Error during comment deletion:', error.message)
    }
    }

/**

  • Main loop flow:
    1. Forces the ._ab81 element to 10000px height.
    1. Waits 30 seconds.
    1. Gradually scrolls down the page in 60s (increments of 200 steps).
    1. Clicks on "Select", selects 99 items, and deletes them.
    1. Infinite loop.
      */
      async function deleteActivity() {
      try {
      while (true) {
      // 1) Capture the 2nd button => "Select"
      const allButtons = document.querySelectorAll('[role="button"]')
      const selectButton = allButtons[1]
      if (!selectButton) {
      throw new Error('Select button not found')
      }

      // 2) Force the ._ab81 element to 10000px height.
      const targetDiv = document.querySelector('._ab81')
      if (targetDiv) {
      targetDiv.style.setProperty('height', '10000px', 'important')
      targetDiv.style.setProperty('overflow', 'hidden', 'important')
      }

      // 3) Wait 30 seconds before any action
      await delay(30000)

      // 4) Now the slow scroll occurs over 1 minute (60000ms) in 200 steps
      await slowScrollDown(10000, 10)

      // 5) Click on "Select"
      await clickElement(selectButton)
      await delay(DELAY_BETWEEN_ACTIONS_MS)

      // 6) Check for "wrong"
      await handleWrongMessage()

      // 7) Search for checkboxes
      const checkboxes = document.querySelectorAll('[aria-label="Toggle checkbox"]')
      if (checkboxes.length === 0) {
      console.log('No more comments to delete')
      return
      }

      // 8) Select up to 99
      for (let i = 0; i < Math.min(DELETION_BATCH_SIZE, checkboxes.length); i++) {
      await clickElement(checkboxes[i])
      await delay(DELAY_BETWEEN_CHECKBOX_CLICKS_MS)
      }

      // 9) Delete
      await delay(DELAY_BETWEEN_ACTIONS_MS)
      await deleteSelectedComments()
      await delay(DELAY_BETWEEN_ACTIONS_MS)

      // 10) Check for "wrong"
      await handleWrongMessage()

      // 11) Wait for "Select" to appear again
      await waitForSelectButton()
      await delay(DELAY_BETWEEN_ACTIONS_MS)

      // 12) Check for "wrong" again
      await handleWrongMessage()
      }
      } catch (error) {
      console.error('Error in deleteActivity:', error.message)
      }
      }

// Infinite loop: if it ends or an error occurs, it restarts
while (true) {
try {
await deleteActivity()
console.log('Activity deletion completed')
} catch (error) {
console.error('Fatal error:', error.message)
}
// Wait 2s and restart
await delay(2000)
}
})()

@sbolel
Copy link
Author

sbolel commented Feb 16, 2025

@gabriellobato1987 wow thanks for the contribution! I'm glad to hear this helped you out. I'll check out your changes and update the original with the diff. I'll also add a contributors line in the header comment block.

thanks again for putting in time to improve this.

Copy link

ghost commented Feb 19, 2025

Hey now it suddenly shows You havent commented anything thts wierd cuz it was at 6weeks before comments only i am new to it can u help ?

@gabriellobato1987
Copy link

Run the new code and let it running without intervene... it will load the comments, this message you saw is an error from instagram and it happens a lot, that's why the new script runs in a infinite loop.

@lwell
Copy link

lwell commented Feb 20, 2025

THANK YOU!! I've been looking for this for years. i let it run for 3 hours while I was working, and it worked flawlessly. Even though at one point Instagram glitched and the page stopped refreshing, it still managed to delete everything.

@Junklov2r
Copy link

I tried it in both chrome and firefox and it doesn't work at all ,doesn't select any of the boxes

this message keeps popping up ;

No more comments to delete VM140:93
Activity deletion completed VM140:116

@gabriellobato1987
Copy link

I tried it in both chrome and firefox and it doesn't work at all ,doesn't select any of the boxes

this message keeps popping up ;

No more comments to delete VM140:93 Activity deletion completed VM140:116

Did you use the first one or the new one a few comments bellow?
This error "No more comments to delete" its an error from Instagram, that's why the new version has a infinite loop, so it keeps running until instagram gets more comments.

@Junklov2r
Copy link

I tried it in both chrome and firefox and it doesn't work at all ,doesn't select any of the boxes
this message keeps popping up ;
No more comments to delete VM140:93 Activity deletion completed VM140:116

Did you use the first one or the new one a few comments bellow? This error "No more comments to delete" its an error from Instagram, that's why the new version has a infinite loop, so it keeps running until instagram gets more comments.

I tried both and it doesn't work at all, I left it running for about 2 hours, it doesn't select boxes and comments are not deleted

@65156
Copy link

65156 commented Feb 28, 2025

I get this error now

VM522:98 Error during comment deletion: Element with selector "button[tabindex="0"]" not found within 30000ms

any ideas?

@justaguy101-yup
Copy link

it does not seem to find the deletion button. I am a doctor so almost no knowledge about these stuff, I tried to fix it with AI but nope.

@bg2183
Copy link

bg2183 commented Mar 30, 2025

Hi there,
I'm getting the following error. Any workarounds?
Screenshot 2025-03-30 at 3 36 43 PM

@TungTungTungTungSahur
Copy link

Doesn't delete the comments, please fix.

@matthieulbrn
Copy link

Agree with Tung, the version doesn't work.

@braunglasrakete
Copy link

braunglasrakete commented Apr 14, 2025

After several tries, I got it fixed. I created a fork, feel free to give it a try.

@sociallyawkwardbats
Copy link

i'm having the same issue as justaguy and 65156 where it can't find the delete button

@braunglasrakete
Copy link

i'm having the same issue as justaguy and 65156 where it can't find the delete button

use my fork, it works mostly for now
https://gist.github.com/braunglasrakete/837a136af79b43f1de8af41170849601

@sociallyawkwardbats
Copy link

sociallyawkwardbats commented Jun 1, 2025

i'm having the same issue as justaguy and 65156 where it can't find the delete button

use my fork, it works mostly for now https://gist.github.com/braunglasrakete/837a136af79b43f1de8af41170849601

oh it works! thank you!!! but now it does the thing where it stops working because instagram takes loads of time to reload

@DeltaOmegas
Copy link

doesn't work anymore :(

@sbolel
Copy link
Author

sbolel commented Jun 24, 2025

doesn't work anymore :(

@DeltaOmegas they most likely changed the DOM enough by now that the selectors are not valid anymore.

I'll try to check it out soon and see if I can find a solution.

@matthieulbrn
Copy link

So I used ChatGPT to pump a lil bit the code and to make it work with the French version, it works !
Only problem is: sometimes Instagram doesn’t show at all the comments (no alert messages, just « You have no comments » but that is a lie).
The solution is to write a new comment but I don’t know how to automate this process…
My idea: write in the same publication the comment «test » and then get back to the comment page to continue the job.
I will send my code by tomorrow, have a nice day!

@matthieulbrn
Copy link

matthieulbrn commented Jun 26, 2025

There it is (WRITTEN IN FRENCH, BE CAREFUL):

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] Nettoyeur Instagram : %(message)s", level=logging.INFO)

MODE = -1
CHECK_EVERY = -1
LIKES_URL = "https://www.instagram.com/your_activity/interactions/likes"
COMMENTS_URL = "https://www.instagram.com/your_activity/interactions/comments"
AT_ONCE_DELETE = 50

logging.info("Lancement du 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("Navigateur Chrome lancé")

    #while (mode := input("Tape 1 pour effacer les commentaires, 2 pour effacer les likes [1/2] : ").strip()) not in ["1", "2"]:
    #    pass
    MODE = 1 #int(mode)

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

    # Connexion
    while True:
        if driver.current_url.startswith(URL):
            logging.info("Connexion détectée")
            break
        try:
            logging.info("En attente de connexion (connecte-toi dans le navigateur sans cliquer ailleurs après) ...")
            wait = WebDriverWait(driver, 60)

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

            wait.until(is_not_now_div_present)
            driver.find_element(By.CSS_SELECTOR, "div[role='button']").send_keys(Keys.ENTER)
            logging.info("Cliqué sur 'Plus tard'")
            break
        except TimeoutException:
            pass

    # Boucle principale
    while True:
        is_clicked_select = False
        while not is_clicked_select:
            logging.info("Chargement des éléments en cours...")
            time.sleep(2)
            elements = driver.find_elements(By.CSS_SELECTOR, 'span[data-bloks-name="bk.components.Text"]')
            for i in elements:
                if i.text == "Sélectionner" or i.text == "Select":
                    no_results = any(j.text == "Aucun résultat" or j.text == "No results" for j in elements)
                    if no_results:
                        logging.info("Aucun élément trouvé. Terminé.")
                        driver.quit()
                        sys.exit(0)
                    driver.execute_script("arguments[0].click();", i)
                    logging.info("Cliqué sur 'Sélectionner'")
                    is_clicked_select = True
                    break

        selected_count = 0
        while_it_count = 0
        is_refreshed = False

        while selected_count == 0:
            if is_refreshed:
                break
            time.sleep(1)
            for i in driver.find_elements(By.CSS_SELECTOR, 'div[data-bloks-name="ig.components.Icon"]'):
                try:
                    if i.get_attribute("style").startswith('mask-image: url("https://i.instagram.com/static/images/bloks/icons/generated/circle__outline'):
                        driver.execute_script("arguments[0].click();", i)
                        selected_count += 1
                        logging.info(f"Élément sélectionné (Total : {selected_count})")
                        if selected_count == AT_ONCE_DELETE:
                            break
                except StaleElementReferenceException:
                    continue

            while_it_count += 1
            if while_it_count > 10:
                if CHECK_EVERY == -1:
                    logging.warning("Limite de suppression atteinte. Instagram bloque temporairement. Attente nécessaire.")
                    '''while (choice := input("Tu veux [1] quitter ou [2] attendre et réessayer ? [1/2] : ").strip()) not in ["1", "2"]:
                        pass
                    if choice == "1":
                        logging.info("Fermeture du script...")
                        driver.quit()
                        sys.exit(0)'''
                    while True:
                        hours_check_every = input("Vérifier toutes les x heure(s) (par défaut : 1) [x] : ")
                        try:
                            hours_check_every = float(hours_check_every or "1")
                            break
                        except:
                            pass
                    CHECK_EVERY = int(hours_check_every * 3600)
                    logging.info(f"Attente de {hours_check_every} heure(s) avant de réessayer.")
                time.sleep(random.uniform(CHECK_EVERY * 0.9, CHECK_EVERY * 1.1))
                logging.info("Rafraîchissement de la page...")
                driver.refresh()
                is_refreshed = True
                continue
        if is_refreshed:
            continue

        # Cliquer sur Supprimer/Retirer
        for i in driver.find_elements(By.CSS_SELECTOR, 'span[data-bloks-name="bk.components.TextSpan"]'):
            if i.text == ("Supprimer" if MODE == 1 else "Je n’aime plus") or i.text == ("Delete" if MODE == 1 else "Unlike"):
                time.sleep(1)
                driver.execute_script("arguments[0].click();", i)
                logging.info(f"Clique sur '{i.text}' effectué")
                break

        # Confirmer la suppression
        is_clicked_confirmation = False
        while not is_clicked_confirmation:
            time.sleep(1)
            for i in driver.find_elements(By.CSS_SELECTOR, 'div[role="dialog"] button'):
                try:
                    confirmation_text = i.find_element(By.CSS_SELECTOR, "div").text
                    if confirmation_text in ["Supprimer", "Je n’aime plus", "Delete", "Unlike"]:
                        logging.info(f"Confirmation : {confirmation_text}")
                        driver.execute_script("arguments[0].click();", i)
                        logging.info(f"Confirmation '{confirmation_text}' cliquée")
                        is_clicked_confirmation = True
                        break
                except StaleElementReferenceException:
                    continue

except KeyboardInterrupt:
    logging.info("Script interrompu manuellement.")
    driver.quit()
    sys.exit(0)
except NoSuchWindowException:
    logging.exception("La fenêtre du navigateur a été fermée.")
    sys.exit(1)
except Exception as e:
    logging.exception("Erreur inattendue :")
    try:
        driver.quit()
    except:
        pass
    sys.exit(1)

So this work until there is the "bug" screen I was talking about (cf quote), and so I promt this code:

Only problem is: sometimes Instagram doesn’t show at all the comments (no alert messages, just « You have no comments » but that is a lie).

import time
import pathlib
import platform
import logging

from selenium import webdriver
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
from selenium.webdriver.support import expected_conditions as EC

# Configuration
URL_COMMENTAIRES = "https://www.instagram.com/your_activity/interactions/comments"
URL_POST_PUBLIC = "https://www.instagram.com/p/DLBBroviviP/"  # ← mets ici le vrai lien
COMMENTAIRE_TEST = "Test - commentaire automatique 💬"

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

# Initialisation du navigateur avec le profil Chrome
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)
wait = WebDriverWait(driver, 15)


def ajouter_commentaire_test_si_aucun_commentaire():
    """Ajoute un commentaire test s'il n'y en a aucun affiché."""
    driver.get(URL_COMMENTAIRES)
    logging.info("Accès à la page des commentaires Instagram")
    time.sleep(5)

    try:
        body_text = driver.find_element(By.TAG_NAME, "body").text

        if ("Vous n’avez laissé aucun commentaire" in body_text or
            "Lorsque vous laissez un commentaire" in body_text or
            "No comments" in body_text):
            logging.info("Aucun commentaire détecté → ajout d'un commentaire de test.")
            publier_commentaire_sur_post_public()
            logging.info("Retour à la page des commentaires pour relecture...")
            driver.get(URL_COMMENTAIRES)
            time.sleep(5)
        else:
            logging.info("Des commentaires sont déjà présents → aucun test nécessaire.")
    except Exception as e:
        logging.warning(f"Erreur lors de la vérification des commentaires : {e}")


def publier_commentaire_sur_post_public():
    """Va sur un post public et publie un commentaire test."""
    try:
        driver.get(URL_POST_PUBLIC)
        logging.info("Ouverture de la publication publique...")
        time.sleep(5)

        # Fermer popup cookie/modal s'il existe
        try:
            bouton_cookie = driver.find_element(By.XPATH, "//button[contains(text(),'Accepter')]")
            bouton_cookie.click()
            logging.info("Popup cookies fermé.")
            time.sleep(2)
        except:
            pass

        # Attendre et cliquer sur le champ de commentaire
        vrai_champ = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "textarea")))
        logging.info("Champ de commentaire trouvé.")
        driver.execute_script("arguments[0].focus(); arguments[0].click();", vrai_champ)
        time.sleep(1)

        # ❗ Relocaliser le champ juste avant l'envoi
        vrai_champ = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "textarea")))
        logging.info("Champ rechargé pour éviter l'erreur stale element.")

        # Saisie et envoi
        vrai_champ.send_keys(COMMENTAIRE_TEST)
        vrai_champ.send_keys(Keys.RETURN)
        logging.info("✅ Commentaire de test publié avec succès.")
        time.sleep(3)

    except Exception as e:
        logging.error(f"❌ Impossible de publier le commentaire de test : {e}")
        driver.save_screenshot("erreur_commentaire.png")


if __name__ == "__main__":
    try:
        ajouter_commentaire_test_si_aucun_commentaire()
    finally:
        logging.info("Fermeture du navigateur.")
        driver.quit()

It works for the recognization but for the rest, nope.

Hope it helps! And tell me if you have the solution to this problem too.

@LuckyLearnsCoding
Copy link

Written on 13/7/2025

I've used chatgpt to update the code so it can be used at this point in time, it uses selenium so be sure to have selenium installed, run this on python:

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 setup
logging.basicConfig(format="[%(levelname)s] Instagram Cleaner: %(message)s", level=logging.INFO)

# Constants
MODE = 1  # 1 = comments, 2 = likes
CHECK_EVERY = -1
LIKES_URL = "https://www.instagram.com/your_activity/interactions/likes"
COMMENTS_URL = "https://www.instagram.com/your_activity/interactions/comments"
AT_ONCE_DELETE = 50  # Maximum items to delete in one go

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
    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 == 0:
            if refreshed:
                break
            time.sleep(1)
            for icon in driver.find_elements(By.CSS_SELECTOR, 'div[data-bloks-name="ig.components.Icon"]'):
                try:
                    if icon.get_attribute("style").startswith('mask-image: url("https://i.instagram.com/static/images/bloks/icons/generated/circle__outline'):
                        driver.execute_script("arguments[0].click();", icon)
                        selected_count += 1
                        logging.info(f"Selected item (Total: {selected_count})")
                        if selected_count >= AT_ONCE_DELETE:
                            break
                except StaleElementReferenceException:
                    continue

            attempts += 1
            if attempts > 10:
                if CHECK_EVERY == -1:
                    logging.warning("Deletion limit hit. Instagram is temporarily blocking actions.")
                    while True:
                        wait_hours = input("Check again after how many hours? (default: 1) [x]: ")
                        try:
                            wait_hours = float(wait_hours or "1")
                            break
                        except ValueError:
                            pass
                    CHECK_EVERY = int(wait_hours * 3600)
                    logging.info(f"Waiting {wait_hours} hour(s) before retrying.")
                time.sleep(random.uniform(CHECK_EVERY * 0.9, CHECK_EVERY * 1.1))
                logging.info("Refreshing page...")
                driver.refresh()
                refreshed = True
                continue
        if refreshed:
            continue

        # Click Delete/Unlike
        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}'")
                break

        # Confirm the deletion
        confirmed = False
        while not confirmed:
            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}'")
                        confirmed = True
                        break
                except StaleElementReferenceException:
                    continue

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)

@LuckyLearnsCoding
Copy link

Written on 13/7/2025

I've used chatgpt to update the code so it can be used at this point in time, it uses selenium so be sure to have selenium installed, run this on python:

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 setup
logging.basicConfig(format="[%(levelname)s] Instagram Cleaner: %(message)s", level=logging.INFO)

# Constants
MODE = 1  # 1 = comments, 2 = likes
CHECK_EVERY = -1
LIKES_URL = "https://www.instagram.com/your_activity/interactions/likes"
COMMENTS_URL = "https://www.instagram.com/your_activity/interactions/comments"
AT_ONCE_DELETE = 50  # Maximum items to delete in one go

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
    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 == 0:
            if refreshed:
                break
            time.sleep(1)
            for icon in driver.find_elements(By.CSS_SELECTOR, 'div[data-bloks-name="ig.components.Icon"]'):
                try:
                    if icon.get_attribute("style").startswith('mask-image: url("https://i.instagram.com/static/images/bloks/icons/generated/circle__outline'):
                        driver.execute_script("arguments[0].click();", icon)
                        selected_count += 1
                        logging.info(f"Selected item (Total: {selected_count})")
                        if selected_count >= AT_ONCE_DELETE:
                            break
                except StaleElementReferenceException:
                    continue

            attempts += 1
            if attempts > 10:
                if CHECK_EVERY == -1:
                    logging.warning("Deletion limit hit. Instagram is temporarily blocking actions.")
                    while True:
                        wait_hours = input("Check again after how many hours? (default: 1) [x]: ")
                        try:
                            wait_hours = float(wait_hours or "1")
                            break
                        except ValueError:
                            pass
                    CHECK_EVERY = int(wait_hours * 3600)
                    logging.info(f"Waiting {wait_hours} hour(s) before retrying.")
                time.sleep(random.uniform(CHECK_EVERY * 0.9, CHECK_EVERY * 1.1))
                logging.info("Refreshing page...")
                driver.refresh()
                refreshed = True
                continue
        if refreshed:
            continue

        # Click Delete/Unlike
        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}'")
                break

        # Confirm the deletion
        confirmed = False
        while not confirmed:
            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}'")
                        confirmed = True
                        break
                except StaleElementReferenceException:
                    continue

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)

edit: for those who dont know how to install selenium do the following:

1.Press Win + R, type cmd, then press Enter.
2. Run These Commands One by One:
python --version pip --version pip install selenium
3. Then its done you can run the code above in python with no problem

@Spiderdoom1313
Copy link

Spiderdoom1313 commented Jul 19, 2025

@gabriellobato1987 your code is by far the most functional, but it simply doesn't ever find the delete button when i use it, it will reset, select the same 40 comments, then hang, then reset, select the same 40 comments, etc etc. is there a line i need to edit?

@SmugFest
Copy link

@Spiderdoom1313 do you have a script but for google chrome, not python required

@111100001
Copy link

Written on 13/7/2025

I've used chatgpt to update the code so it can be used at this point in time, it uses selenium so be sure to have selenium installed, run this on python:

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 setup
logging.basicConfig(format="[%(levelname)s] Instagram Cleaner: %(message)s", level=logging.INFO)

# Constants
MODE = 1  # 1 = comments, 2 = likes
CHECK_EVERY = -1
LIKES_URL = "https://www.instagram.com/your_activity/interactions/likes"
COMMENTS_URL = "https://www.instagram.com/your_activity/interactions/comments"
AT_ONCE_DELETE = 50  # Maximum items to delete in one go

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
    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 == 0:
            if refreshed:
                break
            time.sleep(1)
            for icon in driver.find_elements(By.CSS_SELECTOR, 'div[data-bloks-name="ig.components.Icon"]'):
                try:
                    if icon.get_attribute("style").startswith('mask-image: url("https://i.instagram.com/static/images/bloks/icons/generated/circle__outline'):
                        driver.execute_script("arguments[0].click();", icon)
                        selected_count += 1
                        logging.info(f"Selected item (Total: {selected_count})")
                        if selected_count >= AT_ONCE_DELETE:
                            break
                except StaleElementReferenceException:
                    continue

            attempts += 1
            if attempts > 10:
                if CHECK_EVERY == -1:
                    logging.warning("Deletion limit hit. Instagram is temporarily blocking actions.")
                    while True:
                        wait_hours = input("Check again after how many hours? (default: 1) [x]: ")
                        try:
                            wait_hours = float(wait_hours or "1")
                            break
                        except ValueError:
                            pass
                    CHECK_EVERY = int(wait_hours * 3600)
                    logging.info(f"Waiting {wait_hours} hour(s) before retrying.")
                time.sleep(random.uniform(CHECK_EVERY * 0.9, CHECK_EVERY * 1.1))
                logging.info("Refreshing page...")
                driver.refresh()
                refreshed = True
                continue
        if refreshed:
            continue

        # Click Delete/Unlike
        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}'")
                break

        # Confirm the deletion
        confirmed = False
        while not confirmed:
            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}'")
                        confirmed = True
                        break
                except StaleElementReferenceException:
                    continue

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)

works as of this comment's date

@FinnishArmy
Copy link

As of current, if I run the script it will select the first comment, unselect it then select the next two. It wont find the Delete button element, presumably because it was changed?
Error during comment deletion: Element with selector "button[tabindex="0"]" not found within 30000ms

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