Automating Instagram DMs with Playwright (My First Browser Automation Project)

August 22, 2025 (1mo ago)

3 min read

...

⚑ Recently, I started exploring browser automation as part of my learning journey. I was curious: "Can I automate something like Instagram DMs just for testing?"

So I gave it a try with Playwright + Express.js, and in this blog I’ll share how I built it, the problems I faced, and what I learned. (And yes β€” this is strictly for educational/testing purposes, not spam 🚫)


Info

Before we dive in: - ❌ Don’t use this for bulk DM or spamming. - βœ… Safe for testing, demos, and learning automation. - 🚫 Misuse may get your account flagged.


πŸ“¦ Setting up the Project

First I created a fresh Node.js project and added the dependencies:

{ "name": "browser-automation", "version": "1.0.0", "main": "index.js", "license": "ISC", "dependencies": { "express": "^5.1.0", "playwright": "^1.54.2" } }

Then ran:

pnpm install npx playwright install # takes 5–8 min initially

🧩 Writing the Instagram DM Automation

Here’s the heart of my experiment β€” a simple Express server with a Playwright script.

When I send a request with a username + message, it automatically opens Instagram and sends the DM.

import express from "express"; import { chromium } from "playwright"; const app = express(); app.use(express.json()); const userDataDir = "./instagram_session"; // keeps session // Function to send Instagram DM async function sendInstagramMessage(page, username, message) { try { console.log(`[INFO] Sending message to @${username}...`); await page.goto(`https://www.instagram.com/${username}/`); await page.waitForSelector("text=Message", { timeout: 10000 }); await page.click("text=Message"); const box = page.locator( 'div[aria-label="Message"][contenteditable="true"]', ); await box.click(); for (const char of message) { await page.keyboard.type(char, { delay: 80 + Math.random() * 120 }); } await page.keyboard.press("Enter"); console.log(`[SUCCESS] Message sent to @${username}`); return { success: true }; } catch (err) { console.error(`[ERROR]`, err.message); return { success: false, error: err.message }; } }

πŸ”— Testing the API

I exposed the function through an Express route, so I could test it like this:

curl -X POST http://localhost:3001/instagram \ -H "Content-Type: application/json" \ -d '{"username": "target_username", "message": "Hello from Playwright πŸš€"}'

And boom πŸŽ‰ it worked! Seeing the DM get typed in real-time was very satisfying.


βš™οΈ Sessions & Templates

One thing I learned early: persistent sessions are super useful. By saving the login in ./instagram_session, I didn’t need to log in every time.

I also added support for message templates to avoid hardcoding the text.


πŸ”Œ Bonus: n8n Workflow

Since I also explore automation with n8n, I made a workflow that connects to this server. πŸ‘‰ Check the n8n Template JSON

Now I can trigger Instagram messages via n8n nodes β€” kind of like connecting Lego blocks.


βœ… Key Takeaways

  • Built my first Playwright + Express automation for Instagram DMs.
  • Learned about persistent sessions and API-driven automation.
  • Integrated it with n8n for more flexibility.
  • And most importantly: this project is a reminder that automation is powerful β€” but needs to be used responsibly.

πŸ”₯ This was my first browser automation project with Playwright β€” and honestly, it made me more confident about exploring automation further.

Loading reactions...
Similar Posts

Here are some other articles you might find interesting.

Nitesh's Logo

I'm Nitesh - a full-stack developer, founder and AI innovator. Thanks for visiting my portfolio!

Β© 2025 Nitesh Kushwaha

Automating Instagram DMs with Playwright (My First Browser Automation Project)