Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

InstagramUnsend

Human-supervised Playwright automation for bulk-unsending your own Instagram DMs — one conversation at a time.

Python Playwright License: MIT

unsend.py drives a real Chromium window through Playwright and unsends your outgoing messages from a single Instagram Direct conversation — the ones you'd otherwise have to remove by hand, one hover-menu at a time.

⚠️ Personal / educational tool. Use it only on your own account and only on conversations you own. Unsending is effectively irreversible, and automating Instagram may be contrary to its Terms of Use — use at your own risk. See Safety and privacy.

Instagram Unsend

What is this?

It's deliberately not a hands-off bot. You open the conversation, you confirm, and the script only ever touches messages that Instagram itself confirms are yours (i.e. messages that expose an Unsend option). It never sees your password: authentication comes from a browser session you log into once.

Why I built it

I had a conversation full of years-old messages I wanted gone. Instagram lets you unsend them — but only the slow way: hover a bubble, open the little menu, click Unsend, confirm, repeat. Hundreds of times.

The obvious fix is automation, but I didn't want to hand my Instagram password to a script or a third-party "cleaner." So I built the smallest thing that solves the actual problem: reuse the browser session I'm already logged into, keep a human (me) in the loop, and let Instagram's own UI be the source of truth for what counts as "mine." If a bubble doesn't offer an Unsend button, the script leaves it alone — which means the other person's messages are never at risk.

What it does

  • Opens Instagram Direct in a Chromium window using your saved session.
  • Waits for you to manually open the correct conversation.
  • Scans the visible message list from the bottom up, identifies your own outgoing messages, and unsends them one at a time.
  • Scrolls upward automatically to work through older messages, until it either reaches a configurable maximum or can no longer find any of your messages.

A real run

The script talks to you entirely through the terminal while the browser does the work:

Terminal output from unsend.py

Rendering of the script's actual console output — the prompts, the per-message progress, and the adaptive-scroll messages it prints as it works.

Features

  • Ownership-verified unsends — acts only on messages Instagram lets you unsend.
  • No password handling — authentication comes from your own browser session.
  • Adaptive scrolling — cycles mouse position and applies periodic boost scrolls to handle Instagram's virtualized, dynamically-rendered message list.
  • Human-in-the-loop — you choose the conversation and confirm before anything runs.
  • Tunable — delays, scroll strength, and limits are all constants at the top of the file.

How it works

InstagramUnsend workflow

The automation is a single loop driven entirely by what's currently on screen:

  1. Launch. A persistent Chromium context starts from the local instagram_session/ profile and opens the Direct inbox.
  2. Manual selection. You open the target conversation and press ENTER twice — the script never picks a conversation for you.
  3. Scan (bottom → top). It walks the visible message elements and filters them by geometry: ignoring the header, the message-input area, and anything too small or too large to be a message bubble.
  4. Identify outgoing messages. Candidates on the right-hand side of the conversation are treated as yours (Instagram right-aligns your own messages).
  5. Reveal the menu. It moves the mouse onto the bubble to trigger Instagram's hover-only "more options" control, then opens the message menu.
  6. Confirm ownership. It only proceeds if an Unsend action is present. If it isn't (e.g. an incoming message), the menu is dismissed and the message skipped. This is the safeguard that keeps it off the other person's messages.
  7. Unsend & re-scan. It clicks Unsend, confirms the dialog, then re-scans — because the DOM changes after every removal.
  8. Adaptive scroll. When no outgoing message is visible, it scrolls upward (with a periodic stronger "boost" scroll) to load older messages, stopping after a configurable number of consecutive empty scans.

Safety & human supervision

This is supervised automation, not an unattended bot. The safety model isn't a promise in the docs — it's how the code actually behaves:

Mechanism What it does
Ownership verification Nothing is unsent unless Instagram is showing an Unsend action for that specific message. Incoming messages have no such action, so they're skipped.
No credentials in code The script never asks for or stores your password. It reuses a logged-in session from a local Chromium profile you control.
Visible browser + double confirm It runs non-headless on purpose, and waits for you to open the conversation and press ENTER twice before it does anything.
Bounded execution Hard caps on total messages (MAX_UNSEND) and consecutive empty scans (MAX_EMPTY_SCANS) prevent runaway or infinite loops.
Emergency stop Press Ctrl+C at any moment to halt cleanly.

Tech stack

  • Python 3.9+
  • Playwright for Python (synchronous API)
  • Chromium, bundled and managed by Playwright
  • Session handling via launch_persistent_context with a local user-data directory

Requirements

  • Python 3.9 or newer
  • Playwright for Python — see requirements.txt
  • The Playwright-managed Chromium browser
  • A desktop OS with a visible display (the browser runs non-headless by design)

Installation

# 1. (Recommended) create and activate a virtual environment
python -m venv .venv
# Windows (PowerShell):
.venv\Scripts\Activate.ps1
# macOS / Linux:
source .venv/bin/activate

# 2. Install Python dependencies
pip install -r requirements.txt

# 3. Install the Chromium browser Playwright drives (once)
playwright install chromium

Usage

python unsend.py

On the first run a Chromium window opens. If you're not already logged in, log in to Instagram manually in that window — your session is saved into the local instagram_session/ profile and reused on later runs.

Then:

  1. Wait for Instagram Direct to load.
  2. Open the specific conversation you want to clean up.
  3. Return to the terminal and press ENTER when prompted.
  4. Review the reported limits and press ENTER again to start.
  5. The script unsends your outgoing messages, printing progress as it goes.
  6. Press Ctrl+C at any point to stop immediately.

💡 Test with a small MAX_UNSEND value first to confirm it behaves as you expect.

Configuration

All tunables live at the top of unsend.py:

Variable Default Purpose
MAX_UNSEND 300 Maximum messages to unsend in one run.
DELAY_BETWEEN_UNSEND 1.0 Seconds to wait after each successful unsend.
HOVER_WAIT 0.35 Seconds to wait after hovering a message (to reveal its menu).
MENU_WAIT 0.20 Seconds to wait after opening the message menu.
SCROLL_UP 320 Pixels scrolled up during a normal search scroll.
SCROLL_WAIT 0.65 Seconds to wait after a normal scroll.
MAX_EMPTY_SCANS 80 Consecutive empty scans before the script stops.
BOOST_EVERY 5 Perform a stronger "boost" scroll every N empty scans.
BOOST_SCROLL 850 Pixels per wheel event during a boost scroll.

Higher delays make the automation gentler and more reliable at the cost of speed; lower ones are faster but risk missed messages. Moving too fast can also trip Instagram's rate limiting — keep the defaults unless you have a reason not to.

Safety and privacy

The instagram_session/ directory is a full Chromium user-data profile containing your logged-in Instagram session, cookies, and login data. Anyone who obtains it can access your account.

  • Never commit instagram_session/ to Git. It's excluded in .gitignore — don't override that.
  • Never share, upload, back up publicly, or paste the contents of that directory anywhere.
  • If you suspect it's been exposed, log out of Instagram (which invalidates the session) and delete the directory.

Limitations

  • Instagram's UI/DOM changes over time. The tool relies on the current structure of Instagram's web interface (hover menus, button labels, message layout). Instagram can change these at any time, which may break the automation until selectors are updated.
  • English-language UI only. Message actions are located by their English accessibility labels (e.g. "See more options for message", "Unsend"). Switch the Instagram web UI to English before running, or the locators won't match.
  • Position-based identification. Outgoing messages are identified partly by on-screen position, so unusual window sizes, zoom levels, or very narrow windows can reduce reliability. A normal, reasonably wide window works best.
  • One conversation at a time. It operates on whatever conversation you have open; it doesn't iterate across chats.
  • Virtualized list. Instagram only renders messages near the viewport, so extremely long histories take time to scroll through.
  • Not an official API. This is browser automation, not the Instagram Graph API.

Project structure

InstagramUnsend/
├── unsend.py            # The automation script (entry point)
├── requirements.txt     # Python dependencies (Playwright)
├── docs/                # README assets (hero, workflow diagram, terminal render)
├── README.md            # This file
├── LICENSE              # MIT License
├── .gitignore           # Excludes the session profile and other local files
└── instagram_session/   # Local Chromium profile — git-ignored, never committed

Future improvements

None currently implemented — just directions I'd consider:

  • Language-independent locators so it isn't limited to the English UI.
  • Configuration via CLI flags or environment variables instead of editing constants.
  • Optional verbose/debug logging to make failures easier to diagnose.
  • A light refactor into smaller functions, without changing the automation behavior.

License

Released under the MIT License.

About

Playwright-based Python automation tool for bulk-unsending your own Instagram DM messages.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages